@@ -838,67 +838,132 @@ public Boolean recompute(HasSystemFeatureQuery query) {
838838 }
839839 };
840840
841- private static final String [] featuresPixel = {
842- "com.google.android.apps.photos.PIXEL_2019_PRELOAD" ,
843- "com.google.android.apps.photos.PIXEL_2019_MIDYEAR_PRELOAD" ,
844- "com.google.android.apps.photos.PIXEL_2018_PRELOAD" ,
845- "com.google.android.apps.photos.PIXEL_2017_PRELOAD" ,
846- "com.google.android.feature.PIXEL_2021_MIDYEAR_EXPERIENCE" ,
847- "com.google.android.feature.PIXEL_2020_EXPERIENCE" ,
848- "com.google.android.feature.PIXEL_2020_MIDYEAR_EXPERIENCE" ,
849- "com.google.android.feature.PIXEL_2019_EXPERIENCE" ,
850- "com.google.android.feature.PIXEL_2019_MIDYEAR_EXPERIENCE" ,
851- "com.google.android.feature.PIXEL_2018_EXPERIENCE" ,
852- "com.google.android.feature.PIXEL_2017_EXPERIENCE" ,
853- "com.google.android.feature.PIXEL_EXPERIENCE" ,
854- "com.google.android.feature.GOOGLE_BUILD" ,
855- "com.google.android.feature.GOOGLE_EXPERIENCE"
856- };
857-
858- private static final String [] featuresPixelOthers = {
859- "com.google.android.feature.ASI" ,
860- "com.google.android.feature.ANDROID_ONE_EXPERIENCE" ,
861- "com.google.android.feature.GOOGLE_FI_BUNDLED" ,
862- "com.google.android.feature.LILY_EXPERIENCE" ,
863- "com.google.android.feature.TURBO_PRELOAD" ,
864- "com.google.android.feature.WELLBEING" ,
865- "com.google.lens.feature.IMAGE_INTEGRATION" ,
866- "com.google.lens.feature.CAMERA_INTEGRATION" ,
867- "com.google.photos.trust_debug_certs" ,
868- "com.google.android.feature.AER_OPTIMIZED" ,
869- "com.google.android.feature.NEXT_GENERATION_ASSISTANT" ,
870- "android.software.game_service" ,
871- "com.google.android.feature.EXCHANGE_6_2" ,
872- "com.google.android.apps.dialer.call_recording_audio" ,
873- "com.google.android.apps.dialer.SUPPORTED" ,
874- "com.google.android.feature.CONTEXTUAL_SEARCH" ,
875- "com.google.android.feature.D2D_CABLE_MIGRATION_FEATURE"
876- };
877-
878- private static final String [] featuresTensor = {
879- "com.google.android.feature.PIXEL_2026_EXPERIENCE" ,
880- "com.google.android.feature.PIXEL_2026_MIDYEAR_EXPERIENCE" ,
881- "com.google.android.feature.PIXEL_2025_EXPERIENCE" ,
882- "com.google.android.feature.PIXEL_2025_MIDYEAR_EXPERIENCE" ,
883- "com.google.android.feature.PIXEL_2024_EXPERIENCE" ,
884- "com.google.android.feature.PIXEL_2024_MIDYEAR_EXPERIENCE" ,
885- "com.google.android.feature.PIXEL_2023_EXPERIENCE" ,
886- "com.google.android.feature.PIXEL_2023_MIDYEAR_EXPERIENCE" ,
887- "com.google.android.feature.PIXEL_2022_EXPERIENCE" ,
888- "com.google.android.feature.PIXEL_2022_MIDYEAR_EXPERIENCE" ,
889- "com.google.android.feature.PIXEL_2021_EXPERIENCE"
890- };
891-
892- private static final String [] featuresNexus = {
893- "com.google.android.apps.photos.NEXUS_PRELOAD" ,
894- "com.google.android.apps.photos.nexus_preload" ,
895- "com.google.android.feature.PIXEL_EXPERIENCE" ,
896- "com.google.android.feature.GOOGLE_BUILD" ,
897- "com.google.android.feature.GOOGLE_EXPERIENCE"
898- };
841+ private static final ArraySet <String > PRIV_PKGS = new ArraySet <>();
842+ private static final ArraySet <String > FEATURES_PIXEL = new ArraySet <>();
843+ private static final ArraySet <String > FEATURES_PIXEL_OTHERS = new ArraySet <>();
844+ private static final ArraySet <String > FEATURES_TENSOR = new ArraySet <>();
845+ private static final ArraySet <String > FEATURES_NEXUS = new ArraySet <>();
846+ private static final ArraySet <String > TENSOR_CODENAMES = new ArraySet <>();
847+ private static final boolean IS_TENSOR_DEVICE ;
848+
849+ static {
850+ Collections .addAll (FEATURES_PIXEL ,
851+ "com.google.android.apps.photos.PIXEL_2019_PRELOAD" ,
852+ "com.google.android.apps.photos.PIXEL_2019_MIDYEAR_PRELOAD" ,
853+ "com.google.android.apps.photos.PIXEL_2018_PRELOAD" ,
854+ "com.google.android.apps.photos.PIXEL_2017_PRELOAD" ,
855+ "com.google.android.feature.PIXEL_2021_MIDYEAR_EXPERIENCE" ,
856+ "com.google.android.feature.PIXEL_2020_EXPERIENCE" ,
857+ "com.google.android.feature.PIXEL_2020_MIDYEAR_EXPERIENCE" ,
858+ "com.google.android.feature.PIXEL_2019_EXPERIENCE" ,
859+ "com.google.android.feature.PIXEL_2019_MIDYEAR_EXPERIENCE" ,
860+ "com.google.android.feature.PIXEL_2018_EXPERIENCE" ,
861+ "com.google.android.feature.PIXEL_2017_EXPERIENCE" ,
862+ "com.google.android.feature.PIXEL_EXPERIENCE" ,
863+ "com.google.android.feature.GOOGLE_BUILD" ,
864+ "com.google.android.feature.GOOGLE_EXPERIENCE"
865+ );
866+
867+ Collections .addAll (FEATURES_PIXEL_OTHERS ,
868+ "com.google.android.feature.ASI" ,
869+ "com.google.android.feature.ANDROID_ONE_EXPERIENCE" ,
870+ "com.google.android.feature.GOOGLE_FI_BUNDLED" ,
871+ "com.google.android.feature.LILY_EXPERIENCE" ,
872+ "com.google.android.feature.TURBO_PRELOAD" ,
873+ "com.google.android.feature.WELLBEING" ,
874+ "com.google.lens.feature.IMAGE_INTEGRATION" ,
875+ "com.google.lens.feature.CAMERA_INTEGRATION" ,
876+ "com.google.photos.trust_debug_certs" ,
877+ "com.google.android.feature.AER_OPTIMIZED" ,
878+ "com.google.android.feature.NEXT_GENERATION_ASSISTANT" ,
879+ "android.software.game_service" ,
880+ "com.google.android.feature.EXCHANGE_6_2" ,
881+ "com.google.android.apps.dialer.call_recording_audio" ,
882+ "com.google.android.apps.dialer.SUPPORTED"
883+ );
884+
885+ Collections .addAll (FEATURES_TENSOR ,
886+ "com.google.android.feature.PIXEL_2026_EXPERIENCE" ,
887+ "com.google.android.feature.PIXEL_2026_MIDYEAR_EXPERIENCE" ,
888+ "com.google.android.feature.PIXEL_2025_EXPERIENCE" ,
889+ "com.google.android.feature.PIXEL_2025_MIDYEAR_EXPERIENCE" ,
890+ "com.google.android.feature.PIXEL_2024_EXPERIENCE" ,
891+ "com.google.android.feature.PIXEL_2024_MIDYEAR_EXPERIENCE" ,
892+ "com.google.android.feature.PIXEL_2023_EXPERIENCE" ,
893+ "com.google.android.feature.PIXEL_2023_MIDYEAR_EXPERIENCE" ,
894+ "com.google.android.feature.PIXEL_2022_EXPERIENCE" ,
895+ "com.google.android.feature.PIXEL_2022_MIDYEAR_EXPERIENCE" ,
896+ "com.google.android.feature.PIXEL_2021_EXPERIENCE"
897+ );
898+
899+ Collections .addAll (FEATURES_NEXUS ,
900+ "com.google.android.apps.photos.NEXUS_PRELOAD" ,
901+ "com.google.android.apps.photos.nexus_preload" ,
902+ "com.google.android.feature.PIXEL_EXPERIENCE" ,
903+ "com.google.android.feature.GOOGLE_BUILD" ,
904+ "com.google.android.feature.GOOGLE_EXPERIENCE"
905+ );
906+
907+ Collections .addAll (TENSOR_CODENAMES ,
908+ "stallion" ,"blazer" ,"frankel" ,"mustang" ,"tegu" ,"comet" ,"komodo" ,"caiman" ,"tokay" ,
909+ "akita" ,"husky" ,"shiba" ,"felix" ,"tangorpro" ,"lynx" ,"cheetah" ,"panther" ,
910+ "bluejay" ,"oriole" ,"raven"
911+ );
912+
913+ Collections .addAll (PRIV_PKGS ,
914+ "com.google.android.googlequicksearchbox" ,
915+ "com.google.android.apps.photos" ,
916+ "com.google.android.apps.pixel.agent" ,
917+ "com.google.android.apps.pixel.creativeassistant"
918+ );
919+
920+ final String device = SystemProperties .get ("ro.evolution.device" );
921+ IS_TENSOR_DEVICE = TENSOR_CODENAMES .contains (device );
922+ }
899923
900924 @ Override
901925 public boolean hasSystemFeature (String name , int version ) {
926+ final String pkg = ActivityThread .currentPackageName ();
927+
928+ if (name != null && pkg != null && PRIV_PKGS .contains (pkg )) {
929+ final boolean photosSpoof = "com.google.android.apps.photos" .equals (pkg )
930+ && SystemProperties .getBoolean ("persist.sys.pp.photos" , true );
931+ if (photosSpoof ) {
932+ if (FEATURES_PIXEL .contains (name )) return false ;
933+ if (FEATURES_PIXEL_OTHERS .contains (name )) return true ;
934+ if (FEATURES_TENSOR .contains (name )) return false ;
935+ if (FEATURES_NEXUS .contains (name )) return true ;
936+ } else {
937+ if (FEATURES_PIXEL .contains (name )) return true ;
938+ if (FEATURES_PIXEL_OTHERS .contains (name )) return true ;
939+ if (FEATURES_TENSOR .contains (name )) return true ;
940+ if (FEATURES_NEXUS .contains (name )) return true ;
941+ }
942+ }
943+
944+ if (name != null && FEATURES_TENSOR .contains (name )) {
945+ final boolean forceTensor = SystemProperties .getBoolean (
946+ "persist.sys.pp.tensor" , false );
947+
948+ // Do not interfere with real Tensor devices
949+ if (IS_TENSOR_DEVICE ) {
950+ return mHasSystemFeatureCache .query (
951+ new HasSystemFeatureQuery (name , version ));
952+ }
953+
954+ // Only override if user explicitly enabled the toggle
955+ if (forceTensor ) {
956+ return true ;
957+ }
958+
959+ // Otherwise, behave like stock
960+ return mHasSystemFeatureCache .query (
961+ new HasSystemFeatureQuery (name , version ));
962+ }
963+
964+ if (name != null && FEATURES_PIXEL .contains (name )) return true ;
965+ if (name != null && FEATURES_PIXEL_OTHERS .contains (name )) return true ;
966+
902967 // We check for system features in the following order:
903968 // * Build time-defined system features (constant, very efficient)
904969 // * SDK-defined system features (cached at process start, very efficient)
@@ -916,31 +981,6 @@ public boolean hasSystemFeature(String name, int version) {
916981 return maybeHasSystemFeature ;
917982 }
918983 }
919-
920- String packageName = ActivityThread .currentPackageName ();
921- boolean isPhotosSpoofEnabled = SystemProperties .getBoolean ("persist.sys.pp.photos" , true );
922- if (packageName != null
923- && (packageName .equals ("com.google.android.googlequicksearchbox" )
924- || packageName .equals ("com.google.android.apps.pixel.agent" )
925- || packageName .equals ("com.google.android.apps.pixel.creativeassistant" )
926- || packageName .equals ("com.google.android.dialer" )
927- || (packageName .equals ("com.google.android.apps.photos" )
928- && !isPhotosSpoofEnabled ))) {
929- if (Arrays .asList (featuresPixel ).contains (name )) return true ;
930- if (Arrays .asList (featuresPixelOthers ).contains (name )) return true ;
931- if (Arrays .asList (featuresTensor ).contains (name )) return true ;
932- if (Arrays .asList (featuresNexus ).contains (name )) return true ;
933- }
934- if (packageName != null
935- && packageName .equals ("com.google.android.apps.photos" ) && isPhotosSpoofEnabled ) {
936- if (Arrays .asList (featuresPixel ).contains (name )) return false ;
937- if (Arrays .asList (featuresPixelOthers ).contains (name )) return true ;
938- if (Arrays .asList (featuresTensor ).contains (name )) return false ;
939- if (Arrays .asList (featuresNexus ).contains (name )) return true ;
940- }
941- if (Arrays .asList (featuresNexus ).contains (name )) return true ;
942- if (Arrays .asList (featuresPixel ).contains (name )) return true ;
943- if (Arrays .asList (featuresPixelOthers ).contains (name )) return true ;
944984 return mHasSystemFeatureCache .query (new HasSystemFeatureQuery (name , version ));
945985 }
946986
0 commit comments