diff options
124 files changed, 1878 insertions, 839 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp index e71ded922ae6..8ced596a6762 100644 --- a/AconfigFlags.bp +++ b/AconfigFlags.bp @@ -101,6 +101,7 @@ aconfig_declarations_group { "framework-jobscheduler-job.flags-aconfig-java", "framework_graphics_flags_java_lib", "hwui_flags_java_lib", + "keystore2_flags_java-framework", "power_flags_lib", "sdk_sandbox_flags_lib", "surfaceflinger_flags_java_lib", @@ -374,6 +375,7 @@ java_aconfig_library { min_sdk_version: "30", apex_available: [ "//apex_available:platform", + "com.android.btservices", "com.android.mediaprovider", "com.android.permission", ], diff --git a/Android.bp b/Android.bp index d2e80034423b..dc48668220bc 100644 --- a/Android.bp +++ b/Android.bp @@ -105,7 +105,6 @@ filegroup { ":android.hardware.radio.data-V3-java-source", ":android.hardware.radio.network-V3-java-source", ":android.hardware.radio.voice-V3-java-source", - ":android.hardware.security.keymint-V3-java-source", ":android.hardware.security.secureclock-V1-java-source", ":android.hardware.thermal-V2-java-source", ":android.hardware.tv.tuner-V2-java-source", @@ -114,7 +113,6 @@ filegroup { ":android.security.legacykeystore-java-source", ":android.security.maintenance-java-source", ":android.security.metrics-java-source", - ":android.system.keystore2-V4-java-source", ":android.hardware.cas-V1-java-source", ":credstore_aidl", ":dumpstate_aidl", @@ -149,7 +147,16 @@ filegroup { ":framework-javastream-protos", ":statslog-framework-java-gen", // FrameworkStatsLog.java ":audio_policy_configuration_V7_0", - ], + ] + select(release_flag("RELEASE_ATTEST_MODULES"), { + true: [ + ":android.hardware.security.keymint-V4-java-source", + ":android.system.keystore2-V5-java-source", + ], + default: [ + ":android.hardware.security.keymint-V3-java-source", + ":android.system.keystore2-V4-java-source", + ], + }), } java_library { diff --git a/FF_LEADS_OWNERS b/FF_LEADS_OWNERS new file mode 100644 index 000000000000..a650c6b7a26f --- /dev/null +++ b/FF_LEADS_OWNERS @@ -0,0 +1,10 @@ +bills@google.com +carmenjackson@google.com +nalini@google.com +nosh@google.com +olilan@google.com +philipcuadra@google.com +rajekumar@google.com +shayba@google.com +timmurray@google.com +zezeozue@google.com diff --git a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java index f726361effd6..a88796c38166 100644 --- a/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java +++ b/cmds/uiautomator/library/core-src/com/android/uiautomator/core/AccessibilityNodeInfoDumper.java @@ -217,6 +217,9 @@ public class AccessibilityNodeInfoDumper { serializer.attribute("", "selected", Boolean.toString(node.isSelected())); serializer.attribute("", "bounds", AccessibilityNodeInfoHelper.getVisibleBoundsInScreen( node, width, height).toShortString()); + serializer.attribute("", "drawing-order", Integer.toString(node.getDrawingOrder())); + serializer.attribute("", "hint", safeCharSeqToString(node.getHintText())); + int count = node.getChildCount(); for (int i = 0; i < count; i++) { AccessibilityNodeInfo child = node.getChild(i); diff --git a/core/api/current.txt b/core/api/current.txt index 519deac25177..280e99613914 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -239,6 +239,7 @@ package android { field public static final String PROVIDE_OWN_AUTOFILL_SUGGESTIONS = "android.permission.PROVIDE_OWN_AUTOFILL_SUGGESTIONS"; field public static final String PROVIDE_REMOTE_CREDENTIALS = "android.permission.PROVIDE_REMOTE_CREDENTIALS"; field public static final String QUERY_ALL_PACKAGES = "android.permission.QUERY_ALL_PACKAGES"; + field @FlaggedApi("android.permission.flags.ranging_permission_enabled") public static final String RANGING = "android.permission.RANGING"; field public static final String READ_ASSISTANT_APP_SEARCH_DATA = "android.permission.READ_ASSISTANT_APP_SEARCH_DATA"; field public static final String READ_BASIC_PHONE_STATE = "android.permission.READ_BASIC_PHONE_STATE"; field public static final String READ_CALENDAR = "android.permission.READ_CALENDAR"; @@ -13108,6 +13109,7 @@ package android.content.pm { field public static final String FEATURE_BACKUP = "android.software.backup"; field public static final String FEATURE_BLUETOOTH = "android.hardware.bluetooth"; field public static final String FEATURE_BLUETOOTH_LE = "android.hardware.bluetooth_le"; + field @FlaggedApi("com.android.ranging.flags.ranging_cs_enabled") public static final String FEATURE_BLUETOOTH_LE_CHANNEL_SOUNDING = "android.hardware.bluetooth_le.channel_sounding"; field public static final String FEATURE_CAMERA = "android.hardware.camera"; field public static final String FEATURE_CAMERA_ANY = "android.hardware.camera.any"; field public static final String FEATURE_CAMERA_AR = "android.hardware.camera.ar"; @@ -13509,7 +13511,7 @@ package android.content.pm { field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1 field public static final int FLAG_USE_APP_ZYGOTE = 8; // 0x8 field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_CAMERA}, anyOf={android.Manifest.permission.CAMERA}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_CAMERA = 64; // 0x40 - field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE}, anyOf={android.Manifest.permission.BLUETOOTH_ADVERTISE, android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.CHANGE_NETWORK_STATE, android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, android.Manifest.permission.NFC, android.Manifest.permission.TRANSMIT_IR, android.Manifest.permission.UWB_RANGING}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 16; // 0x10 + field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE}, anyOf={android.Manifest.permission.BLUETOOTH_ADVERTISE, android.Manifest.permission.BLUETOOTH_CONNECT, android.Manifest.permission.BLUETOOTH_SCAN, android.Manifest.permission.CHANGE_NETWORK_STATE, android.Manifest.permission.CHANGE_WIFI_STATE, android.Manifest.permission.CHANGE_WIFI_MULTICAST_STATE, android.Manifest.permission.NFC, android.Manifest.permission.TRANSMIT_IR, android.Manifest.permission.UWB_RANGING, android.Manifest.permission.RANGING}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE = 16; // 0x10 field @RequiresPermission(value=android.Manifest.permission.FOREGROUND_SERVICE_DATA_SYNC, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_DATA_SYNC = 1; // 0x1 field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_HEALTH}, anyOf={android.Manifest.permission.ACTIVITY_RECOGNITION, android.Manifest.permission.BODY_SENSORS, android.Manifest.permission.HIGH_SAMPLING_RATE_SENSORS}) public static final int FOREGROUND_SERVICE_TYPE_HEALTH = 256; // 0x100 field @RequiresPermission(allOf={android.Manifest.permission.FOREGROUND_SERVICE_LOCATION}, anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}, conditional=true) public static final int FOREGROUND_SERVICE_TYPE_LOCATION = 8; // 0x8 @@ -22796,7 +22798,6 @@ package android.media { method public boolean isVendor(); field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_MEMORY_SAFE = 1; // 0x1 field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_SANDBOXED = 0; // 0x0 - field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2; // 0x2 } public static final class MediaCodecInfo.AudioCapabilities { @@ -23687,7 +23688,6 @@ package android.media { field public static final int COLOR_TRANSFER_ST2084 = 6; // 0x6 field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_MEMORY_SAFE = 2; // 0x2 field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_SANDBOXED = 1; // 0x1 - field @FlaggedApi("android.media.codec.in_process_sw_audio_codec") public static final int FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 4; // 0x4 field public static final String KEY_AAC_DRC_ALBUM_MODE = "aac-drc-album-mode"; field public static final String KEY_AAC_DRC_ATTENUATION_FACTOR = "aac-drc-cut-level"; field public static final String KEY_AAC_DRC_BOOST_FACTOR = "aac-drc-boost-level"; @@ -40034,8 +40034,10 @@ package android.security.keystore { method @NonNull public java.util.List<java.security.cert.X509Certificate> getGrantedCertificateChainFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException; method @NonNull public java.security.Key getGrantedKeyFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException; method @NonNull public java.security.KeyPair getGrantedKeyPairFromId(long) throws android.security.keystore.KeyPermanentlyInvalidatedException, java.security.UnrecoverableKeyException; + method @FlaggedApi("android.security.keystore2.attest_modules") @NonNull public byte[] getSupplementaryAttestationInfo(int) throws android.security.KeyStoreException; method public long grantKeyAccess(@NonNull String, int) throws android.security.KeyStoreException, java.security.UnrecoverableKeyException; method public void revokeKeyAccess(@NonNull String, int) throws android.security.KeyStoreException, java.security.UnrecoverableKeyException; + field public static final int MODULE_HASH = -1879047468; // 0x900002d4 } public class SecureKeyImportUnavailableException extends java.security.ProviderException { @@ -45999,6 +46001,8 @@ package android.telephony { method public long getDataUsageBytes(); method public long getDataUsageTime(); method @NonNull public int[] getNetworkTypes(); + method @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") @Nullable public java.time.ZonedDateTime getPlanEndDate(); + method @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public int getSubscriptionStatus(); method @Nullable public CharSequence getSummary(); method @Nullable public CharSequence getTitle(); method public void writeToParcel(android.os.Parcel, int); @@ -46009,6 +46013,11 @@ package android.telephony { field public static final int LIMIT_BEHAVIOR_DISABLED = 0; // 0x0 field public static final int LIMIT_BEHAVIOR_THROTTLED = 2; // 0x2 field public static final int LIMIT_BEHAVIOR_UNKNOWN = -1; // 0xffffffff + field @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public static final int SUBSCRIPTION_STATUS_ACTIVE = 1; // 0x1 + field @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public static final int SUBSCRIPTION_STATUS_INACTIVE = 2; // 0x2 + field @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public static final int SUBSCRIPTION_STATUS_SUSPENDED = 4; // 0x4 + field @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public static final int SUBSCRIPTION_STATUS_TRIAL = 3; // 0x3 + field @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") public static final int SUBSCRIPTION_STATUS_UNKNOWN = 0; // 0x0 field public static final long TIME_UNKNOWN = -1L; // 0xffffffffffffffffL } @@ -46020,6 +46029,7 @@ package android.telephony { method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int); method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long); method @NonNull public android.telephony.SubscriptionPlan.Builder setNetworkTypes(@NonNull int[]); + method @FlaggedApi("com.android.internal.telephony.flags.subscription_plan_allow_status_and_end_date") @NonNull public android.telephony.SubscriptionPlan.Builder setSubscriptionStatus(int); method public android.telephony.SubscriptionPlan.Builder setSummary(@Nullable CharSequence); method public android.telephony.SubscriptionPlan.Builder setTitle(@Nullable CharSequence); } diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 1019ce80c34d..f94c97e2076c 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -684,13 +684,17 @@ package android.app { field public static final String OPSTR_PLAY_AUDIO = "android:play_audio"; field public static final String OPSTR_POST_NOTIFICATION = "android:post_notification"; field public static final String OPSTR_PROJECT_MEDIA = "android:project_media"; + field @FlaggedApi("android.permission.flags.ranging_permission_enabled") public static final String OPSTR_RANGING = "android:ranging"; field @FlaggedApi("android.view.contentprotection.flags.rapid_clear_notifications_by_listener_app_op_enabled") public static final String OPSTR_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER = "android:rapid_clear_notifications_by_listener"; field public static final String OPSTR_READ_CLIPBOARD = "android:read_clipboard"; + field @FlaggedApi("android.permission.flags.replace_body_sensor_permission_enabled") public static final String OPSTR_READ_HEART_RATE = "android:read_heart_rate"; field public static final String OPSTR_READ_ICC_SMS = "android:read_icc_sms"; field public static final String OPSTR_READ_MEDIA_AUDIO = "android:read_media_audio"; field public static final String OPSTR_READ_MEDIA_IMAGES = "android:read_media_images"; field public static final String OPSTR_READ_MEDIA_VIDEO = "android:read_media_video"; field public static final String OPSTR_READ_MEDIA_VISUAL_USER_SELECTED = "android:read_media_visual_user_selected"; + field @FlaggedApi("android.permission.flags.replace_body_sensor_permission_enabled") public static final String OPSTR_READ_OXYGEN_SATURATION = "android:read_oxygen_saturation"; + field @FlaggedApi("android.permission.flags.replace_body_sensor_permission_enabled") public static final String OPSTR_READ_SKIN_TEMPERATURE = "android:read_skin_temperature"; field public static final String OPSTR_READ_WRITE_HEALTH_DATA = "android:read_write_health_data"; field public static final String OPSTR_RECEIVE_AMBIENT_TRIGGER_AUDIO = "android:receive_ambient_trigger_audio"; field public static final String OPSTR_RECEIVE_EMERGENCY_BROADCAST = "android:receive_emergency_broadcast"; diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 79c4fb653542..59327c8afecc 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -2044,6 +2044,29 @@ package android.media { method public boolean isAidlHal(); } + public final class MediaCodec { + method @FlaggedApi("android.media.codec.codec_availability") @NonNull public static java.util.List<android.media.MediaCodec.GlobalResourceInfo> getGloballyAvailableResources(); + method @FlaggedApi("android.media.codec.codec_availability") @NonNull public java.util.List<android.media.MediaCodec.InstanceResourceInfo> getRequiredResources(); + } + + public abstract static class MediaCodec.Callback { + method @FlaggedApi("android.media.codec.codec_availability") public void onRequiredResourcesChanged(@NonNull android.media.MediaCodec); + } + + @FlaggedApi("android.media.codec.codec_availability") public static final class MediaCodec.GlobalResourceInfo { + ctor public MediaCodec.GlobalResourceInfo(); + method public long getAvailable(); + method public long getCapacity(); + method @NonNull public String getName(); + } + + @FlaggedApi("android.media.codec.codec_availability") public static final class MediaCodec.InstanceResourceInfo { + ctor public MediaCodec.InstanceResourceInfo(); + method @NonNull public String getName(); + method public long getPerFrameCount(); + method public long getStaticCount(); + } + public static final class MediaCodecInfo.VideoCapabilities.PerformancePoint { ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(int, int, int, int, @NonNull android.util.Size); ctor public MediaCodecInfo.VideoCapabilities.PerformancePoint(@NonNull android.media.MediaCodecInfo.VideoCapabilities.PerformancePoint, @NonNull android.util.Size); diff --git a/core/java/android/app/AppCompatCallbacks.java b/core/java/android/app/AppCompatCallbacks.java index f2debfcfa6b1..4ef8eb7b93d6 100644 --- a/core/java/android/app/AppCompatCallbacks.java +++ b/core/java/android/app/AppCompatCallbacks.java @@ -28,6 +28,7 @@ import java.util.Arrays; * * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class AppCompatCallbacks implements Compatibility.BehaviorChangeDelegate { private final long[] mDisabledChanges; private final long[] mLoggableChanges; diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index 091d5ab8534d..3eea9033e6c4 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -54,6 +54,7 @@ import android.content.pm.PackageManager; import android.content.pm.ParceledListSlice; import android.database.DatabaseUtils; import android.health.connect.HealthConnectManager; +import android.health.connect.HealthPermissions; import android.media.AudioAttributes.AttributeUsage; import android.media.MediaRouter2; import android.os.Binder; @@ -1608,9 +1609,25 @@ public class AppOpsManager { public static final int OP_RECEIVE_SENSITIVE_NOTIFICATIONS = AppProtoEnums.APP_OP_RECEIVE_SENSITIVE_NOTIFICATIONS; + /** @hide Access to read heart rate sensor. */ + public static final int OP_READ_HEART_RATE = AppProtoEnums.APP_OP_READ_HEART_RATE; + + /** @hide Access to read skin temperature. */ + public static final int OP_READ_SKIN_TEMPERATURE = AppProtoEnums.APP_OP_READ_SKIN_TEMPERATURE; + + /** + * Allows an app to range with nearby devices using any ranging technology available. + * + * @hide + */ + public static final int OP_RANGING = AppProtoEnums.APP_OP_RANGING; + + /** @hide Access to read oxygen saturation. */ + public static final int OP_READ_OXYGEN_SATURATION = AppProtoEnums.APP_OP_READ_OXYGEN_SATURATION; + /** @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - public static final int _NUM_OP = 149; + public static final int _NUM_OP = 153; /** * All app ops represented as strings. @@ -1763,6 +1780,10 @@ public class AppOpsManager { OPSTR_UNARCHIVAL_CONFIRMATION, OPSTR_EMERGENCY_LOCATION, OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS, + OPSTR_READ_HEART_RATE, + OPSTR_READ_SKIN_TEMPERATURE, + OPSTR_RANGING, + OPSTR_READ_OXYGEN_SATURATION, }) public @interface AppOpString {} @@ -2500,6 +2521,26 @@ public class AppOpsManager { public static final String OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS = "android:receive_sensitive_notifications"; + /** @hide Access to read heart rate sensor. */ + @SystemApi + @FlaggedApi(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) + public static final String OPSTR_READ_HEART_RATE = "android:read_heart_rate"; + + /** @hide Access to read oxygen saturation. */ + @SystemApi + @FlaggedApi(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) + public static final String OPSTR_READ_OXYGEN_SATURATION = "android:read_oxygen_saturation"; + + /** @hide Access to read skin temperature. */ + @SystemApi + @FlaggedApi(Flags.FLAG_REPLACE_BODY_SENSOR_PERMISSION_ENABLED) + public static final String OPSTR_READ_SKIN_TEMPERATURE = "android:read_skin_temperature"; + + /** @hide Access to ranging */ + @SystemApi + @FlaggedApi(Flags.FLAG_RANGING_PERMISSION_ENABLED) + public static final String OPSTR_RANGING = "android:ranging"; + /** {@link #sAppOpsToNote} not initialized yet for this op */ private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0; /** Should not collect noting of this app-op in {@link #sAppOpsToNote} */ @@ -2571,8 +2612,13 @@ public class AppOpsManager { OP_BLUETOOTH_ADVERTISE, OP_UWB_RANGING, OP_NEARBY_WIFI_DEVICES, + Flags.rangingPermissionEnabled() ? OP_RANGING : OP_NONE, // Notifications OP_POST_NOTIFICATION, + // Health + Flags.replaceBodySensorPermissionEnabled() ? OP_READ_HEART_RATE : OP_NONE, + Flags.replaceBodySensorPermissionEnabled() ? OP_READ_SKIN_TEMPERATURE : OP_NONE, + Flags.replaceBodySensorPermissionEnabled() ? OP_READ_OXYGEN_SATURATION : OP_NONE, }; /** @@ -3080,6 +3126,24 @@ public class AppOpsManager { new AppOpInfo.Builder(OP_RECEIVE_SENSITIVE_NOTIFICATIONS, OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS, "RECEIVE_SENSITIVE_NOTIFICATIONS") .setDefaultMode(MODE_IGNORED).build(), + new AppOpInfo.Builder(OP_READ_HEART_RATE, OPSTR_READ_HEART_RATE, "READ_HEART_RATE") + .setPermission(Flags.replaceBodySensorPermissionEnabled() + ? HealthPermissions.READ_HEART_RATE : null) + .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), + new AppOpInfo.Builder(OP_READ_SKIN_TEMPERATURE, OPSTR_READ_SKIN_TEMPERATURE, + "READ_SKIN_TEMPERATURE").setPermission( + Flags.replaceBodySensorPermissionEnabled() + ? HealthPermissions.READ_SKIN_TEMPERATURE : null) + .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), + new AppOpInfo.Builder(OP_RANGING, OPSTR_RANGING, "RANGING") + .setPermission(Flags.rangingPermissionEnabled() + ? Manifest.permission.RANGING : null) + .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), + new AppOpInfo.Builder(OP_READ_OXYGEN_SATURATION, OPSTR_READ_OXYGEN_SATURATION, + "READ_OXYGEN_SATURATION").setPermission( + Flags.replaceBodySensorPermissionEnabled() + ? HealthPermissions.READ_OXYGEN_SATURATION : null) + .setDefaultMode(AppOpsManager.MODE_ALLOWED).build(), }; // The number of longs needed to form a full bitmask of app ops @@ -3133,6 +3197,10 @@ public class AppOpsManager { } } for (int op : RUNTIME_PERMISSION_OPS) { + if (op == OP_NONE) { + // Skip ops with a disabled feature flag. + continue; + } if (sAppOpInfos[op].permission != null) { sPermToOp.put(sAppOpInfos[op].permission, op); } diff --git a/core/java/android/app/ForegroundServiceTypePolicy.java b/core/java/android/app/ForegroundServiceTypePolicy.java index d1e517bbd03c..16444dc5adde 100644 --- a/core/java/android/app/ForegroundServiceTypePolicy.java +++ b/core/java/android/app/ForegroundServiceTypePolicy.java @@ -398,6 +398,7 @@ public abstract class ForegroundServiceTypePolicy { new RegularPermission(Manifest.permission.NFC), new RegularPermission(Manifest.permission.TRANSMIT_IR), new RegularPermission(Manifest.permission.UWB_RANGING), + new RegularPermission(Manifest.permission.RANGING), new UsbDevicePermission(), new UsbAccessoryPermission(), }, false), diff --git a/core/java/android/app/compat/ChangeIdStateCache.java b/core/java/android/app/compat/ChangeIdStateCache.java index dea4e9c82f56..a185d6a48a62 100644 --- a/core/java/android/app/compat/ChangeIdStateCache.java +++ b/core/java/android/app/compat/ChangeIdStateCache.java @@ -29,13 +29,24 @@ import com.android.internal.compat.IPlatformCompat; * Handles caching of calls to {@link com.android.internal.compat.IPlatformCompat} * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class ChangeIdStateCache extends PropertyInvalidatedCache<ChangeIdStateQuery, Boolean> { private static final String CACHE_KEY = "cache_key.is_compat_change_enabled"; private static final int MAX_ENTRIES = 64; - private static boolean sDisabled = false; + private static boolean sDisabled = getDefaultDisabled(); private volatile IPlatformCompat mPlatformCompat; + + @android.ravenwood.annotation.RavenwoodReplace + private static boolean getDefaultDisabled() { + return false; + } + + private static boolean getDefaultDisabled$ravenwood() { + return true; // TODO(b/376676753) Disable the cache for now. + } + /** @hide */ public ChangeIdStateCache() { super(MAX_ENTRIES, CACHE_KEY); diff --git a/core/java/android/app/compat/ChangeIdStateQuery.java b/core/java/android/app/compat/ChangeIdStateQuery.java index 7598d6c90d3d..26d9ab65417e 100644 --- a/core/java/android/app/compat/ChangeIdStateQuery.java +++ b/core/java/android/app/compat/ChangeIdStateQuery.java @@ -35,6 +35,7 @@ import java.util.Objects; * @hide */ @Immutable +@android.ravenwood.annotation.RavenwoodKeepWholeClass final class ChangeIdStateQuery { static final int QUERY_BY_PACKAGE_NAME = 0; diff --git a/core/java/android/app/compat/CompatChanges.java b/core/java/android/app/compat/CompatChanges.java index d7b2ab4351a4..643d4c96f7b9 100644 --- a/core/java/android/app/compat/CompatChanges.java +++ b/core/java/android/app/compat/CompatChanges.java @@ -39,6 +39,7 @@ import java.util.Set; * @hide */ @SystemApi +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatChanges { private static final ChangeIdStateCache QUERY_CACHE = new ChangeIdStateCache(); diff --git a/core/java/android/app/compat/PackageOverride.java b/core/java/android/app/compat/PackageOverride.java index ebc2945fb1a0..ffc1eec05667 100644 --- a/core/java/android/app/compat/PackageOverride.java +++ b/core/java/android/app/compat/PackageOverride.java @@ -36,6 +36,7 @@ import java.util.Objects; * @hide */ @SystemApi +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class PackageOverride { /** @hide */ diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index 8de86d5b60a0..0ed9c87e3d51 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -292,6 +292,10 @@ public abstract class PackageManager { * <p> * The value of a property will only have a single type, as defined by * the property itself. + * + * <p class="note"><strong>Note:</strong> + * In android version {@link Build.VERSION_CODES#VANILLA_ICE_CREAM} and earlier, + * the {@code equals} and {@code hashCode} methods for this class may not function as expected. */ public static final class Property implements Parcelable { private static final int TYPE_BOOLEAN = 1; @@ -523,6 +527,40 @@ public abstract class PackageManager { return new Property[size]; } }; + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Property)) { + return false; + } + final Property property = (Property) obj; + return mType == property.mType && + Objects.equals(mName, property.mName) && + Objects.equals(mClassName, property.mClassName) && + Objects.equals(mPackageName, property.mPackageName) && + (mType == TYPE_BOOLEAN ? mBooleanValue == property.mBooleanValue : + mType == TYPE_FLOAT ? Float.compare(mFloatValue, property.mFloatValue) == 0 : + mType == TYPE_INTEGER ? mIntegerValue == property.mIntegerValue : + mType == TYPE_RESOURCE ? mIntegerValue == property.mIntegerValue : + mStringValue.equals(property.mStringValue)); + } + + @Override + public int hashCode() { + int result = Objects.hash(mName, mType, mClassName, mPackageName); + if (mType == TYPE_BOOLEAN) { + result = 31 * result + (mBooleanValue ? 1 : 0); + } else if (mType == TYPE_FLOAT) { + result = 31 * result + Float.floatToIntBits(mFloatValue); + } else if (mType == TYPE_INTEGER) { + result = 31 * result + mIntegerValue; + } else if (mType == TYPE_RESOURCE) { + result = 31 * result + mIntegerValue; + } else if (mType == TYPE_STRING) { + result = 31 * result + mStringValue.hashCode(); + } + return result; + } } /** @@ -3126,6 +3164,16 @@ public abstract class PackageManager { /** * Feature for {@link #getSystemAvailableFeatures} and + * {@link #hasSystemFeature}: The device is capable of ranging with + * other devices using channel sounding via Bluetooth Low Energy radio. + */ + @FlaggedApi(com.android.ranging.flags.Flags.FLAG_RANGING_CS_ENABLED) + @SdkConstant(SdkConstantType.FEATURE) + public static final String FEATURE_BLUETOOTH_LE_CHANNEL_SOUNDING = + "android.hardware.bluetooth_le.channel_sounding"; + + /** + * Feature for {@link #getSystemAvailableFeatures} and * {@link #hasSystemFeature}: The device has a camera facing away * from the screen. */ diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java index 5b0cee75e591..4285b0a2b91a 100644 --- a/core/java/android/content/pm/ServiceInfo.java +++ b/core/java/android/content/pm/ServiceInfo.java @@ -251,6 +251,7 @@ public class ServiceInfo extends ComponentInfo * {@link android.Manifest.permission#NFC}, * {@link android.Manifest.permission#TRANSMIT_IR}, * {@link android.Manifest.permission#UWB_RANGING}, + * {@link android.Manifest.permission#RANGING}, * or has been granted the access to one of the attached USB devices/accessories. */ @RequiresPermission( @@ -267,6 +268,7 @@ public class ServiceInfo extends ComponentInfo Manifest.permission.NFC, Manifest.permission.TRANSMIT_IR, Manifest.permission.UWB_RANGING, + Manifest.permission.RANGING, }, conditional = true ) diff --git a/core/java/android/hardware/contexthub/OWNERS b/core/java/android/hardware/contexthub/OWNERS new file mode 100644 index 000000000000..a65a2bf9ee36 --- /dev/null +++ b/core/java/android/hardware/contexthub/OWNERS @@ -0,0 +1,2 @@ +# ContextHub team +file:platform/system/chre:/OWNERS diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS index 590ddb404b63..e63b6648a9ef 100644 --- a/core/java/android/os/OWNERS +++ b/core/java/android/os/OWNERS @@ -78,6 +78,9 @@ per-file PatternMatcher* = file:/PACKAGE_MANAGER_OWNERS # PermissionEnforcer per-file PermissionEnforcer.java = tweek@google.com, brufino@google.com +# RemoteCallbackList +per-file RemoteCallbackList.java = shayba@google.com + # ART per-file ArtModuleServiceManager.java = file:platform/art:/OWNERS @@ -125,3 +128,6 @@ per-file StatsServiceManager.java = file:/services/core/java/com/android/server/ # Dropbox per-file DropBoxManager* = mwachens@google.com + +# Flags +per-file flags.aconfig = file:/FF_LEADS_OWNERS diff --git a/core/java/android/permission/flags.aconfig b/core/java/android/permission/flags.aconfig index e029e520f1b1..5c54ecdc3336 100644 --- a/core/java/android/permission/flags.aconfig +++ b/core/java/android/permission/flags.aconfig @@ -213,3 +213,21 @@ flag { purpose: PURPOSE_BUGFIX } } + +flag { + name: "replace_body_sensor_permission_enabled" + is_fixed_read_only: true + is_exported: true + namespace: "android_health_services" + description: "Enables replacement of BODY_SENSORS/BODY_SENSORS_BACKGROUND permissions with granular health permissions READ_HEART_RATE, READ_SKIN_TEMPERATURE, READ_OXYGEN_SATURATION, and READ_HEALTH_DATA_IN_BACKGROUND" + bug: "364638912" +} + +flag { + name: "ranging_permission_enabled" + is_fixed_read_only: true + is_exported: true + namespace: "uwb" + description: "This fixed read-only flag is used to enable new ranging permission for all ranging use cases." + bug: "370977414" +} diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index 3f4f79072124..5d1d7583d8f8 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -115,6 +115,14 @@ flag { } flag { + name: "protect_device_config_flags" + namespace: "psap_ai" + description: "Feature flag to limit adb shell to allowlisted flags" + bug: "364083026" + is_fixed_read_only: true +} + +flag { name: "keystore_grant_api" namespace: "hardware_backed_security" description: "Feature flag for exposing KeyStore grant APIs" diff --git a/core/java/android/telephony/SubscriptionPlan.java b/core/java/android/telephony/SubscriptionPlan.java index 7b48a16c2227..4c59a8589df2 100644 --- a/core/java/android/telephony/SubscriptionPlan.java +++ b/core/java/android/telephony/SubscriptionPlan.java @@ -18,6 +18,7 @@ package android.telephony; import android.annotation.BytesLong; import android.annotation.CurrentTimeMillisLong; +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -28,6 +29,7 @@ import android.telephony.Annotation.NetworkType; import android.util.Range; import android.util.RecurrenceRule; +import com.android.internal.telephony.flags.Flags; import com.android.internal.util.Preconditions; import java.lang.annotation.Retention; @@ -83,6 +85,33 @@ public final class SubscriptionPlan implements Parcelable { /** Value indicating a timestamp is unknown. */ public static final long TIME_UNKNOWN = -1; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "SUBSCRIPTION_STATUS_" }, value = { + SUBSCRIPTION_STATUS_UNKNOWN, + SUBSCRIPTION_STATUS_ACTIVE, + SUBSCRIPTION_STATUS_INACTIVE, + SUBSCRIPTION_STATUS_TRIAL, + SUBSCRIPTION_STATUS_SUSPENDED + }) + public @interface SubscriptionStatus {} + + /** Subscription status is unknown. */ + @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE) + public static final int SUBSCRIPTION_STATUS_UNKNOWN = 0; + /** Subscription is active. */ + @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE) + public static final int SUBSCRIPTION_STATUS_ACTIVE = 1; + /** Subscription is inactive. */ + @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE) + public static final int SUBSCRIPTION_STATUS_INACTIVE = 2; + /** Subscription is in a trial period. */ + @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE) + public static final int SUBSCRIPTION_STATUS_TRIAL = 3; + /** Subscription is suspended. */ + @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE) + public static final int SUBSCRIPTION_STATUS_SUSPENDED = 4; + private final RecurrenceRule cycleRule; private CharSequence title; private CharSequence summary; @@ -91,6 +120,7 @@ public final class SubscriptionPlan implements Parcelable { private long dataUsageBytes = BYTES_UNKNOWN; private long dataUsageTime = TIME_UNKNOWN; private @NetworkType int[] networkTypes; + private int mSubscriptionStatus = SUBSCRIPTION_STATUS_UNKNOWN; private SubscriptionPlan(RecurrenceRule cycleRule) { this.cycleRule = Preconditions.checkNotNull(cycleRule); @@ -107,6 +137,7 @@ public final class SubscriptionPlan implements Parcelable { dataUsageBytes = source.readLong(); dataUsageTime = source.readLong(); networkTypes = source.createIntArray(); + mSubscriptionStatus = source.readInt(); } @Override @@ -124,6 +155,7 @@ public final class SubscriptionPlan implements Parcelable { dest.writeLong(dataUsageBytes); dest.writeLong(dataUsageTime); dest.writeIntArray(networkTypes); + dest.writeInt(mSubscriptionStatus); } @Override @@ -137,13 +169,14 @@ public final class SubscriptionPlan implements Parcelable { .append(" dataUsageBytes=").append(dataUsageBytes) .append(" dataUsageTime=").append(dataUsageTime) .append(" networkTypes=").append(Arrays.toString(networkTypes)) + .append(" subscriptionStatus=").append(mSubscriptionStatus) .append("}").toString(); } @Override public int hashCode() { return Objects.hash(cycleRule, title, summary, dataLimitBytes, dataLimitBehavior, - dataUsageBytes, dataUsageTime, Arrays.hashCode(networkTypes)); + dataUsageBytes, dataUsageTime, Arrays.hashCode(networkTypes), mSubscriptionStatus); } @Override @@ -157,7 +190,8 @@ public final class SubscriptionPlan implements Parcelable { && dataLimitBehavior == other.dataLimitBehavior && dataUsageBytes == other.dataUsageBytes && dataUsageTime == other.dataUsageTime - && Arrays.equals(networkTypes, other.networkTypes); + && Arrays.equals(networkTypes, other.networkTypes) + && mSubscriptionStatus == other.mSubscriptionStatus; } return false; } @@ -179,6 +213,13 @@ public final class SubscriptionPlan implements Parcelable { return cycleRule; } + /** Return the end date of this plan, or null if no end date exists. */ + @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE) + public @Nullable ZonedDateTime getPlanEndDate() { + // ZonedDateTime is immutable, so no need to create a defensive copy. + return cycleRule.end; + } + /** Return the short title of this plan. */ public @Nullable CharSequence getTitle() { return title; @@ -238,6 +279,16 @@ public final class SubscriptionPlan implements Parcelable { } /** + * Returns the status of the subscription plan. + * + * @return The subscription status, or {@link #SUBSCRIPTION_STATUS_UNKNOWN} if not available. + */ + @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE) + public @SubscriptionStatus int getSubscriptionStatus() { + return mSubscriptionStatus; + } + + /** * Builder for a {@link SubscriptionPlan}. */ public static class Builder { @@ -382,5 +433,21 @@ public final class SubscriptionPlan implements Parcelable { TelephonyManager.getAllNetworkTypes().length); return this; } + + /** + * Set the subscription status. + * + * @param subscriptionStatus the current subscription status + */ + @FlaggedApi(Flags.FLAG_SUBSCRIPTION_PLAN_ALLOW_STATUS_AND_END_DATE) + public @NonNull Builder setSubscriptionStatus(@SubscriptionStatus int subscriptionStatus) { + if (subscriptionStatus < SUBSCRIPTION_STATUS_UNKNOWN + || subscriptionStatus > SUBSCRIPTION_STATUS_SUSPENDED) { + throw new IllegalArgumentException( + "Subscription status must be defined with a valid value"); + } + plan.mSubscriptionStatus = subscriptionStatus; + return this; + } } } diff --git a/core/java/com/android/internal/compat/AndroidBuildClassifier.java b/core/java/com/android/internal/compat/AndroidBuildClassifier.java index 364db06976a0..19f8889996dc 100644 --- a/core/java/com/android/internal/compat/AndroidBuildClassifier.java +++ b/core/java/com/android/internal/compat/AndroidBuildClassifier.java @@ -22,6 +22,7 @@ import android.os.Build; * Platform private class for determining the type of Android build installed. * */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public class AndroidBuildClassifier { public boolean isDebuggableBuild() { diff --git a/core/java/com/android/internal/compat/ChangeReporter.java b/core/java/com/android/internal/compat/ChangeReporter.java index ded142ce49e5..bfa122b8aa6d 100644 --- a/core/java/com/android/internal/compat/ChangeReporter.java +++ b/core/java/com/android/internal/compat/ChangeReporter.java @@ -42,6 +42,7 @@ import java.util.function.Function; * * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class ChangeReporter { private static final String TAG = "CompatChangeReporter"; private static final Function<Integer, Set<ChangeReport>> NEW_CHANGE_REPORT_SET = diff --git a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java index 182dba71d0d7..8fd914aecf55 100644 --- a/core/java/com/android/internal/compat/CompatibilityChangeConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityChangeConfig.java @@ -28,6 +28,7 @@ import java.util.Set; * Parcelable containing compat config overrides for a given application. * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatibilityChangeConfig implements Parcelable { private final ChangeConfig mChangeConfig; diff --git a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java index 03fe4551c249..505fd2319a6b 100644 --- a/core/java/com/android/internal/compat/CompatibilityChangeInfo.java +++ b/core/java/com/android/internal/compat/CompatibilityChangeInfo.java @@ -25,6 +25,7 @@ import android.os.Parcelable; * * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public class CompatibilityChangeInfo implements Parcelable { private final long mChangeId; private final @Nullable String mName; diff --git a/core/java/com/android/internal/compat/CompatibilityOverrideConfig.java b/core/java/com/android/internal/compat/CompatibilityOverrideConfig.java index 9a02b7b7aae9..32206c9950dd 100644 --- a/core/java/com/android/internal/compat/CompatibilityOverrideConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityOverrideConfig.java @@ -28,6 +28,7 @@ import java.util.Map; * Parcelable containing compat config overrides for a given application. * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatibilityOverrideConfig implements Parcelable { public final Map<Long, PackageOverride> overrides; diff --git a/core/java/com/android/internal/compat/CompatibilityOverridesByPackageConfig.java b/core/java/com/android/internal/compat/CompatibilityOverridesByPackageConfig.java index 8652bb6d05e4..998b48a8a76e 100644 --- a/core/java/com/android/internal/compat/CompatibilityOverridesByPackageConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityOverridesByPackageConfig.java @@ -26,6 +26,7 @@ import java.util.Map; * Parcelable containing compat config overrides by application. * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatibilityOverridesByPackageConfig implements Parcelable { public final Map<String, CompatibilityOverrideConfig> packageNameToOverrides; diff --git a/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveByPackageConfig.java b/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveByPackageConfig.java index b408d6440070..c0e2217d509e 100644 --- a/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveByPackageConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveByPackageConfig.java @@ -29,6 +29,7 @@ import java.util.Map; * IDs. * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatibilityOverridesToRemoveByPackageConfig implements Parcelable { public final Map<String, CompatibilityOverridesToRemoveConfig> packageNameToOverridesToRemove; diff --git a/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveConfig.java b/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveConfig.java index e85afefdc39a..10461ec0b4c6 100644 --- a/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveConfig.java +++ b/core/java/com/android/internal/compat/CompatibilityOverridesToRemoveConfig.java @@ -30,6 +30,7 @@ import java.util.Set; * <p>This class is separate from CompatibilityOverrideConfig since we only need change IDs. * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatibilityOverridesToRemoveConfig implements Parcelable { public final Set<Long> changeIds; diff --git a/core/java/com/android/internal/compat/OverrideAllowedState.java b/core/java/com/android/internal/compat/OverrideAllowedState.java index e408be2ab471..f018c3a830bd 100644 --- a/core/java/com/android/internal/compat/OverrideAllowedState.java +++ b/core/java/com/android/internal/compat/OverrideAllowedState.java @@ -27,6 +27,7 @@ import java.lang.annotation.RetentionPolicy; /** * This class contains all the possible override allowed states. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class OverrideAllowedState implements Parcelable { @IntDef({ ALLOWED, diff --git a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java index a69d2e4f4dca..8df3f2abcafd 100644 --- a/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java +++ b/core/java/com/android/internal/ravenwood/RavenwoodEnvironment.java @@ -15,6 +15,12 @@ */ package com.android.internal.ravenwood; +import static android.os.Build.VERSION_CODES.S; +import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE; + +import android.compat.annotation.ChangeId; +import android.compat.annotation.Disabled; +import android.compat.annotation.EnabledAfter; import android.ravenwood.annotation.RavenwoodKeepWholeClass; import android.ravenwood.annotation.RavenwoodRedirect; import android.ravenwood.annotation.RavenwoodRedirectionClass; @@ -78,4 +84,24 @@ public final class RavenwoodEnvironment { public String getRavenwoodRuntimePath() { throw notSupportedOnDevice(); } + + /** @hide */ + public static class CompatIdsForTest { + // Enabled by default + /** Used for testing */ + @ChangeId + public static final long TEST_COMPAT_ID_1 = 368131859L; + + /** Used for testing */ + @Disabled + @ChangeId public static final long TEST_COMPAT_ID_2 = 368131701L; + + /** Used for testing */ + @EnabledAfter(targetSdkVersion = S) + @ChangeId public static final long TEST_COMPAT_ID_3 = 368131659L; + + /** Used for testing */ + @EnabledAfter(targetSdkVersion = UPSIDE_DOWN_CAKE) + @ChangeId public static final long TEST_COMPAT_ID_4 = 368132057L; + } } diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp index 4cc904153aac..4369cb0d82b4 100644 --- a/core/jni/android_util_Process.cpp +++ b/core/jni/android_util_Process.cpp @@ -33,6 +33,7 @@ #include <algorithm> #include <array> +#include <cctype> #include <cstring> #include <limits> #include <memory> @@ -1004,6 +1005,8 @@ jboolean android_os_Process_parseProcLineArray(JNIEnv* env, jobject clazz, } } if ((mode&PROC_OUT_STRING) != 0 && di < NS) { + std::replace_if(buffer+start, buffer+end, + [](unsigned char c){ return !std::isprint(c); }, '?'); jstring str = env->NewStringUTF(buffer+start); env->SetObjectArrayElement(outStrings, di, str); } diff --git a/core/jni/com_android_internal_content_FileSystemUtils.cpp b/core/jni/com_android_internal_content_FileSystemUtils.cpp index 6c72544a7958..76ead2a3ca31 100644 --- a/core/jni/com_android_internal_content_FileSystemUtils.cpp +++ b/core/jni/com_android_internal_content_FileSystemUtils.cpp @@ -22,7 +22,6 @@ #include <android-base/hex.h> #include <android-base/unique_fd.h> #include <bionic/macros.h> -#include <elf.h> #include <errno.h> #include <fcntl.h> #include <inttypes.h> @@ -204,7 +203,8 @@ bool punchHoles(const char *filePath, const uint64_t offset, return true; } -bool punchHolesInElf64(const char *filePath, const uint64_t offset) { +bool getLoadSegmentPhdrs(const char *filePath, const uint64_t offset, + std::vector<Elf64_Phdr> &programHeaders) { // Open Elf file Elf64_Ehdr ehdr; std::ifstream inputStream(filePath, std::ifstream::in); @@ -227,11 +227,6 @@ bool punchHolesInElf64(const char *filePath, const uint64_t offset) { uint64_t programHeaderOffset = ehdr.e_phoff; uint16_t programHeaderNum = ehdr.e_phnum; - IF_ALOGD() { - ALOGD("Punching holes in file: %s programHeaderOffset: %" PRIu64 " programHeaderNum: %hu", - filePath, programHeaderOffset, programHeaderNum); - } - // if this is a zip file, also consider elf offset inside a file uint64_t phOffset; if (__builtin_add_overflow(offset, programHeaderOffset, &phOffset)) { @@ -240,7 +235,6 @@ bool punchHolesInElf64(const char *filePath, const uint64_t offset) { } inputStream.seekg(phOffset); - std::vector<Elf64_Phdr> programHeaders; for (int headerIndex = 0; headerIndex < programHeaderNum; headerIndex++) { Elf64_Phdr header; inputStream.read((char *)&header, sizeof(header)); @@ -254,6 +248,15 @@ bool punchHolesInElf64(const char *filePath, const uint64_t offset) { programHeaders.push_back(header); } + return true; +} + +bool punchHolesInElf64(const char *filePath, const uint64_t offset) { + std::vector<Elf64_Phdr> programHeaders; + if (!getLoadSegmentPhdrs(filePath, offset, programHeaders)) { + ALOGE("Failed to read program headers from ELF file."); + return false; + } return punchHoles(filePath, offset, programHeaders); } diff --git a/core/jni/com_android_internal_content_FileSystemUtils.h b/core/jni/com_android_internal_content_FileSystemUtils.h index 52445e2b4229..4a95686c5a0c 100644 --- a/core/jni/com_android_internal_content_FileSystemUtils.h +++ b/core/jni/com_android_internal_content_FileSystemUtils.h @@ -15,8 +15,11 @@ */ #pragma once +#include <elf.h> #include <sys/types.h> +#include <vector> + namespace android { /* @@ -35,4 +38,11 @@ bool punchHolesInElf64(const char* filePath, uint64_t offset); */ bool punchHolesInZip(const char* filePath, uint64_t offset, uint16_t extraFieldLen); +/* + * This function reads program headers from ELF file. ELF can be specified with file path directly + * or it should be at offset inside Apk. Program headers passed to function is populated. + */ +bool getLoadSegmentPhdrs(const char* filePath, const uint64_t offset, + std::vector<Elf64_Phdr>& programHeaders); + } // namespace android
\ No newline at end of file diff --git a/core/res/Android.bp b/core/res/Android.bp index a44e92ca4019..4254a47877da 100644 --- a/core/res/Android.bp +++ b/core/res/Android.bp @@ -163,6 +163,7 @@ android_app { "android.net.platform.flags-aconfig", "com.android.window.flags.window-aconfig", "android.permission.flags-aconfig", + "ranging_aconfig_flags", ], } diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index e4c56a613f12..101ba119b496 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -2406,6 +2406,16 @@ android:label="@string/permlab_nearby_wifi_devices" android:protectionLevel="dangerous" /> + <!-- Required to be able to range to devices using generic ranging module. + @FlaggedApi("android.permission.flags.ranging_permission_enabled") + <p>Protection level: dangerous --> + <permission android:name="android.permission.RANGING" + android:permissionGroup="android.permission-group.UNDEFINED" + android:description="@string/permdesc_ranging" + android:label="@string/permlab_ranging" + android:protectionLevel="dangerous" + android:featureFlag="android.permission.flags.ranging_permission_enabled"/> + <!-- @SystemApi @TestApi Allows an application to suspend other apps, which will prevent the user from using them until they are unsuspended. @hide diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 1a2f0ccb06ba..aa192ec8d454 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1770,6 +1770,11 @@ <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=140]--> <string name="permdesc_nearby_wifi_devices">Allows the app to advertise, connect, and determine the relative position of nearby Wi\u2011Fi devices</string> + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=50]--> + <string name="permlab_ranging">determine relative position between nearby devices</string> + <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=120]--> + <string name="permdesc_ranging">Allow the app to determine relative position between nearby devices</string> + <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. --> <string name="permlab_preferredPaymentInfo">Preferred NFC Payment Service Information</string> <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. --> diff --git a/core/tests/coretests/src/android/os/OWNERS b/core/tests/coretests/src/android/os/OWNERS index 6149382d0800..4620cb8d8148 100644 --- a/core/tests/coretests/src/android/os/OWNERS +++ b/core/tests/coretests/src/android/os/OWNERS @@ -12,3 +12,6 @@ per-file PerformanceHintManagerTest.java = file:/ADPF_OWNERS # Caching per-file IpcDataCache* = file:/PERFORMANCE_OWNERS + +# RemoteCallbackList +per-file RemoteCallbackListTest.java = shayba@google.com diff --git a/data/sounds/Android.bp b/data/sounds/Android.bp new file mode 100644 index 000000000000..65d4872cdc16 --- /dev/null +++ b/data/sounds/Android.bp @@ -0,0 +1,304 @@ +// Copyright (C) 2024 The Android Open Source Project +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +phony { + name: "frameworks_sounds", + required: [ + "frameworks_alarm_sounds", + "frameworks_notifications_sounds", + "frameworks_ringtones_sounds", + "frameworks_ui_sounds", + "frameworks_ui_48k_sounds", + ], +} + +prebuilt_media { + name: "frameworks_alarm_sounds", + srcs: [ + "Alarm_Beep_01.ogg", + "Alarm_Beep_02.ogg", + "Alarm_Beep_03.ogg", + "Alarm_Buzzer.ogg", + "Alarm_Classic.ogg", + "Alarm_Rooster_02.ogg", + "alarms/ogg/Argon.ogg", + "alarms/ogg/Barium.ogg", + "alarms/ogg/Carbon.ogg", + "alarms/ogg/Helium.ogg", + "alarms/ogg/Krypton.ogg", + "alarms/ogg/Neon.ogg", + "alarms/ogg/Neptunium.ogg", + "alarms/ogg/Osmium.ogg", + "alarms/ogg/Oxygen.ogg", + "alarms/ogg/Platinum.ogg", + "alarms/ogg/Promethium.ogg", + "alarms/ogg/Scandium.ogg", + ], + relative_install_path: "audio/alarms", + product_specific: true, + no_full_install: true, +} + +prebuilt_media { + name: "frameworks_notifications_sounds", + srcs: [ + "notifications/ogg/Adara.ogg", + "notifications/Aldebaran.ogg", + "notifications/Altair.ogg", + "notifications/ogg/Alya.ogg", + "notifications/Antares.ogg", + "notifications/ogg/Antimony.ogg", + "notifications/ogg/Arcturus.ogg", + "notifications/ogg/Argon.ogg", + "notifications/Beat_Box_Android.ogg", + "notifications/ogg/Bellatrix.ogg", + "notifications/ogg/Beryllium.ogg", + "notifications/Betelgeuse.ogg", + "newwavelabs/CaffeineSnake.ogg", + "notifications/Canopus.ogg", + "notifications/ogg/Capella.ogg", + "notifications/Castor.ogg", + "notifications/ogg/CetiAlpha.ogg", + "notifications/ogg/Cobalt.ogg", + "notifications/Cricket.ogg", + "newwavelabs/DearDeer.ogg", + "notifications/Deneb.ogg", + "notifications/Doink.ogg", + "newwavelabs/DontPanic.ogg", + "notifications/Drip.ogg", + "notifications/Electra.ogg", + "F1_MissedCall.ogg", + "F1_New_MMS.ogg", + "F1_New_SMS.ogg", + "notifications/ogg/Fluorine.ogg", + "notifications/Fomalhaut.ogg", + "notifications/ogg/Gallium.ogg", + "notifications/Heaven.ogg", + "notifications/ogg/Helium.ogg", + "newwavelabs/Highwire.ogg", + "notifications/ogg/Hojus.ogg", + "notifications/ogg/Iridium.ogg", + "notifications/ogg/Krypton.ogg", + "newwavelabs/KzurbSonar.ogg", + "notifications/ogg/Lalande.ogg", + "notifications/Merope.ogg", + "notifications/ogg/Mira.ogg", + "newwavelabs/OnTheHunt.ogg", + "notifications/ogg/Palladium.ogg", + "notifications/Plastic_Pipe.ogg", + "notifications/ogg/Polaris.ogg", + "notifications/ogg/Pollux.ogg", + "notifications/ogg/Procyon.ogg", + "notifications/ogg/Proxima.ogg", + "notifications/ogg/Radon.ogg", + "notifications/ogg/Rubidium.ogg", + "notifications/ogg/Selenium.ogg", + "notifications/ogg/Shaula.ogg", + "notifications/Sirrah.ogg", + "notifications/SpaceSeed.ogg", + "notifications/ogg/Spica.ogg", + "notifications/ogg/Strontium.ogg", + "notifications/ogg/Syrma.ogg", + "notifications/TaDa.ogg", + "notifications/ogg/Talitha.ogg", + "notifications/ogg/Tejat.ogg", + "notifications/ogg/Thallium.ogg", + "notifications/Tinkerbell.ogg", + "notifications/ogg/Upsilon.ogg", + "notifications/ogg/Vega.ogg", + "newwavelabs/Voila.ogg", + "notifications/ogg/Xenon.ogg", + "notifications/ogg/Zirconium.ogg", + "notifications/arcturus.ogg", + "notifications/moonbeam.ogg", + "notifications/pixiedust.ogg", + "notifications/pizzicato.ogg", + "notifications/regulus.ogg", + "notifications/sirius.ogg", + "notifications/tweeters.ogg", + "notifications/vega.ogg", + ], + relative_install_path: "audio/notifications", + product_specific: true, + no_full_install: true, +} + +prebuilt_media { + name: "frameworks_ringtones_sounds", + srcs: [ + "ringtones/ANDROMEDA.ogg", + "ringtones/ogg/Andromeda.ogg", + "ringtones/ogg/Aquila.ogg", + "ringtones/ogg/ArgoNavis.ogg", + "ringtones/ogg/Atria.ogg", + "ringtones/BOOTES.ogg", + "newwavelabs/Backroad.ogg", + "newwavelabs/BeatPlucker.ogg", + "newwavelabs/BentleyDubs.ogg", + "newwavelabs/Big_Easy.ogg", + "newwavelabs/BirdLoop.ogg", + "newwavelabs/Bollywood.ogg", + "newwavelabs/BussaMove.ogg", + "ringtones/CANISMAJOR.ogg", + "ringtones/CASSIOPEIA.ogg", + "newwavelabs/Cairo.ogg", + "newwavelabs/Calypso_Steel.ogg", + "ringtones/ogg/CanisMajor.ogg", + "newwavelabs/CaribbeanIce.ogg", + "ringtones/ogg/Carina.ogg", + "ringtones/ogg/Centaurus.ogg", + "newwavelabs/Champagne_Edition.ogg", + "newwavelabs/Club_Cubano.ogg", + "newwavelabs/CrayonRock.ogg", + "newwavelabs/CrazyDream.ogg", + "newwavelabs/CurveBall.ogg", + "ringtones/ogg/Cygnus.ogg", + "newwavelabs/DancinFool.ogg", + "newwavelabs/Ding.ogg", + "newwavelabs/DonMessWivIt.ogg", + "ringtones/ogg/Draco.ogg", + "newwavelabs/DreamTheme.ogg", + "newwavelabs/Eastern_Sky.ogg", + "newwavelabs/Enter_the_Nexus.ogg", + "ringtones/Eridani.ogg", + "newwavelabs/EtherShake.ogg", + "ringtones/FreeFlight.ogg", + "newwavelabs/FriendlyGhost.ogg", + "newwavelabs/Funk_Yall.ogg", + "newwavelabs/GameOverGuitar.ogg", + "newwavelabs/Gimme_Mo_Town.ogg", + "ringtones/ogg/Girtab.ogg", + "newwavelabs/Glacial_Groove.ogg", + "newwavelabs/Growl.ogg", + "newwavelabs/HalfwayHome.ogg", + "ringtones/ogg/Hydra.ogg", + "newwavelabs/InsertCoin.ogg", + "ringtones/ogg/Kuma.ogg", + "newwavelabs/LoopyLounge.ogg", + "newwavelabs/LoveFlute.ogg", + "ringtones/Lyra.ogg", + "ringtones/ogg/Machina.ogg", + "newwavelabs/MidEvilJaunt.ogg", + "newwavelabs/MildlyAlarming.ogg", + "newwavelabs/Nairobi.ogg", + "newwavelabs/Nassau.ogg", + "newwavelabs/NewPlayer.ogg", + "newwavelabs/No_Limits.ogg", + "newwavelabs/Noises1.ogg", + "newwavelabs/Noises2.ogg", + "newwavelabs/Noises3.ogg", + "newwavelabs/OrganDub.ogg", + "ringtones/ogg/Orion.ogg", + "ringtones/PERSEUS.ogg", + "newwavelabs/Paradise_Island.ogg", + "ringtones/ogg/Pegasus.ogg", + "ringtones/ogg/Perseus.ogg", + "newwavelabs/Playa.ogg", + "ringtones/ogg/Pyxis.ogg", + "ringtones/ogg/Rasalas.ogg", + "newwavelabs/Revelation.ogg", + "ringtones/ogg/Rigel.ogg", + "Ring_Classic_02.ogg", + "Ring_Digital_02.ogg", + "Ring_Synth_02.ogg", + "Ring_Synth_04.ogg", + "newwavelabs/Road_Trip.ogg", + "newwavelabs/RomancingTheTone.ogg", + "newwavelabs/Safari.ogg", + "newwavelabs/Savannah.ogg", + "ringtones/ogg/Scarabaeus.ogg", + "ringtones/ogg/Sceptrum.ogg", + "newwavelabs/Seville.ogg", + "newwavelabs/Shes_All_That.ogg", + "newwavelabs/SilkyWay.ogg", + "newwavelabs/SitarVsSitar.ogg", + "ringtones/ogg/Solarium.ogg", + "newwavelabs/SpringyJalopy.ogg", + "newwavelabs/Steppin_Out.ogg", + "newwavelabs/Terminated.ogg", + "ringtones/Testudo.ogg", + "ringtones/ogg/Themos.ogg", + "newwavelabs/Third_Eye.ogg", + "newwavelabs/Thunderfoot.ogg", + "newwavelabs/TwirlAway.ogg", + "ringtones/URSAMINOR.ogg", + "ringtones/ogg/UrsaMinor.ogg", + "newwavelabs/VeryAlarmed.ogg", + "ringtones/Vespa.ogg", + "newwavelabs/World.ogg", + "ringtones/ogg/Zeta.ogg", + "ringtones/hydra.ogg", + ], + relative_install_path: "audio/ringtones", + product_specific: true, + no_full_install: true, +} + +prebuilt_media { + name: "frameworks_ui_48k_sounds", + srcs: [ + "effects/ogg/Effect_Tick_48k.ogg", + "effects/ogg/KeypressDelete_120_48k.ogg", + "effects/ogg/KeypressReturn_120_48k.ogg", + "effects/ogg/KeypressSpacebar_120_48k.ogg", + "effects/ogg/KeypressStandard_120_48k.ogg", + "effects/ogg/KeypressInvalid_120_48k.ogg", + "effects/ogg/Trusted_48k.ogg", + "effects/ogg/VideoRecord_48k.ogg", + "effects/ogg/VideoStop_48k.ogg", + "effects/ogg/camera_click_48k.ogg", + ], + dsts: [ + "Effect_Tick.ogg", + "KeypressDelete.ogg", + "KeypressReturn.ogg", + "KeypressSpacebar.ogg", + "KeypressStandard.ogg", + "KeypressInvalid.ogg", + "Trusted.ogg", + "VideoRecord.ogg", + "VideoStop.ogg", + "camera_click.ogg", + ], + relative_install_path: "audio/ui", + product_specific: true, + no_full_install: true, +} + +prebuilt_media { + name: "frameworks_ui_sounds", + srcs: [ + "effects/ogg/Dock.ogg", + "effects/ogg/Lock.ogg", + "effects/ogg/LowBattery.ogg", + "effects/ogg/Undock.ogg", + "effects/ogg/Unlock.ogg", + "effects/ogg/WirelessChargingStarted.ogg", + "effects/ogg/camera_focus.ogg", + "effects/ogg/ChargingStarted.ogg", + "effects/ogg/InCallNotification.ogg", + "effects/ogg/NFCFailure.ogg", + "effects/ogg/NFCInitiated.ogg", + "effects/ogg/NFCSuccess.ogg", + "effects/ogg/NFCTransferComplete.ogg", + "effects/ogg/NFCTransferInitiated.ogg", + ], + relative_install_path: "audio/ui", + product_specific: true, + no_full_install: true, +} diff --git a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java index cae5d8e6846d..35b2375fbc46 100644 --- a/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java +++ b/errorprone/java/com/google/errorprone/bugpatterns/android/EfficientParcelableChecker.java @@ -96,7 +96,7 @@ public final class EfficientParcelableChecker extends BugChecker } if (WRITE_PARCELABLE.matches(tree, state)) { return buildDescription(tree) - .setMessage("Recommended to use 'item.writeToParcel()' to improve " + .setMessage("Recommended to use 'writeTypedObject()' to improve " + "efficiency; saves overhead of Parcelable class name") .build(); } diff --git a/keystore/java/Android.bp b/keystore/java/Android.bp index 21edff1e1c96..264ac5ff1d92 100644 --- a/keystore/java/Android.bp +++ b/keystore/java/Android.bp @@ -13,5 +13,13 @@ filegroup { "**/*.java", "**/*.aidl", ], + exclude_srcs: select(release_flag("RELEASE_ATTEST_MODULES"), { + true: [ + "android/security/KeyStore2HalCurrent.java", + ], + default: [ + "android/security/KeyStore2HalLatest.java", + ], + }), visibility: ["//frameworks/base"], } diff --git a/keystore/java/android/security/KeyStore2.java b/keystore/java/android/security/KeyStore2.java index dd703f5eefb9..f5cf571ad955 100644 --- a/keystore/java/android/security/KeyStore2.java +++ b/keystore/java/android/security/KeyStore2.java @@ -101,7 +101,7 @@ public class KeyStore2 { R execute(IKeystoreService service) throws RemoteException; } - private <R> R handleRemoteExceptionWithRetry(@NonNull CheckedRemoteRequest<R> request) + <R> R handleRemoteExceptionWithRetry(@NonNull CheckedRemoteRequest<R> request) throws KeyStoreException { IKeystoreService service = getService(false /* retryLookup */); boolean firstTry = true; @@ -369,6 +369,18 @@ public class KeyStore2 { } } + /** + * Returns tag-specific info required to interpret a tag's attested value. + * @see IKeystoreService#getSupplementaryAttestationInfo(Tag) for more details. + * @param tag + * @return + * @throws KeyStoreException + * @hide + */ + public byte[] getSupplementaryAttestationInfo(int tag) throws KeyStoreException { + return KeyStore2HalVersion.getSupplementaryAttestationInfoHelper(tag, this); + } + static KeyStoreException getKeyStoreException(int errorCode, String serviceErrorMessage) { if (errorCode > 0) { // KeyStore layer error diff --git a/keystore/java/android/security/KeyStore2HalCurrent.java b/keystore/java/android/security/KeyStore2HalCurrent.java new file mode 100644 index 000000000000..f4d8fe65c995 --- /dev/null +++ b/keystore/java/android/security/KeyStore2HalCurrent.java @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +/** + * @hide This class is necessary to allow the version of the AIDL interface for Keystore and +* KeyMint used in KeyStore2.java to differ by BUILD flag `RELEASE_ATTEST_MODULES`. When +* `RELEASE_ATTEST_MODULES` is not set, this file is included, and the current HALs for Keystore +* (V4) and KeyMint (V3) are used. +*/ +class KeyStore2HalVersion { + public static byte[] getSupplementaryAttestationInfoHelper(int tag, KeyStore2 ks) + throws KeyStoreException { + return new byte[0]; + } +} diff --git a/keystore/java/android/security/KeyStore2HalLatest.java b/keystore/java/android/security/KeyStore2HalLatest.java new file mode 100644 index 000000000000..b6e1cbb4cbb6 --- /dev/null +++ b/keystore/java/android/security/KeyStore2HalLatest.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security; + +/** + * @hide This class is necessary to allow the version of the AIDL interface for Keystore and +* KeyMint used in KeyStore2.java to differ by BUILD flag `RELEASE_ATTEST_MODULES`. When +* `RELEASE_ATTEST_MODULES` is set, this file is included, and the latest HALs for Keystore (V5) +* and KeyMint (V4) are used. +*/ +class KeyStore2HalVersion { + public byte[] getSupplementaryAttestationInfoHelper(int tag, KeyStore2 ks) + throws KeyStoreException { + return ks.handleRemoteExceptionWithRetry( + (service) -> service.getSupplementaryAttestationInfo(tag)); + } +} diff --git a/keystore/java/android/security/keystore/KeyStoreManager.java b/keystore/java/android/security/keystore/KeyStoreManager.java index e6091c1da8a5..740ccb53a691 100644 --- a/keystore/java/android/security/keystore/KeyStoreManager.java +++ b/keystore/java/android/security/keystore/KeyStoreManager.java @@ -17,9 +17,11 @@ package android.security.keystore; import android.annotation.FlaggedApi; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.SystemService; import android.content.Context; +import android.hardware.security.keymint.TagType; import android.security.KeyStore2; import android.security.KeyStoreException; import android.security.keystore2.AndroidKeyStoreProvider; @@ -32,6 +34,8 @@ import android.util.Log; import com.android.internal.annotations.GuardedBy; import java.io.ByteArrayInputStream; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.security.Key; import java.security.KeyPair; import java.security.PublicKey; @@ -299,6 +303,37 @@ public final class KeyStoreManager { return Collections.emptyList(); } + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(value = {MODULE_HASH}) + public @interface SupplementaryAttestationInfoTagEnum {} + + /** + * When passed into getSupplementaryAttestationInfo, getSupplementaryAttestationInfo returns the + * DER-encoded structure corresponding to the `Modules` schema described in the KeyMint HAL's + * KeyCreationResult.aidl. The SHA-256 hash of this encoded structure is what's included with + * the tag in attestations. + */ + // TODO(b/369375199): Replace with Tag.MODULE_HASH when flagging is removed. + public static final int MODULE_HASH = TagType.BYTES | 724; + + /** + * Returns tag-specific data required to interpret a tag's attested value. + * + * When performing key attestation, the obtained attestation certificate contains a list of tags + * and their corresponding attested values. For some tags, additional information about the + * attested value can be queried via this API. See individual tags for specifics. + * + * @param tag tag for which info is being requested + * @return tag-specific info + * @throws KeyStoreException if the requested info is not available + */ + @FlaggedApi(android.security.keystore2.Flags.FLAG_ATTEST_MODULES) + public @NonNull byte[] getSupplementaryAttestationInfo( + @SupplementaryAttestationInfoTagEnum int tag) throws KeyStoreException { + return mKeyStore2.getSupplementaryAttestationInfo(tag); + } + /** * Returns a new {@link KeyDescriptor} instance in the app domain / namespace with the {@code * alias} set to the provided value. diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index 2ae89d3300c1..82e950365850 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -16,6 +16,7 @@ package android.media; +import static android.media.codec.Flags.FLAG_CODEC_AVAILABILITY; import static android.media.codec.Flags.FLAG_NULL_OUTPUT_SURFACE; import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST; import static android.media.codec.Flags.FLAG_SUBSESSION_METRICS; @@ -29,6 +30,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; import android.annotation.SystemApi; +import android.annotation.TestApi; import android.compat.annotation.UnsupportedAppUsage; import android.graphics.ImageFormat; import android.graphics.Rect; @@ -1843,6 +1845,12 @@ final public class MediaCodec { */ private static final int CB_METRICS_FLUSHED = 8; + /** + * Callback ID to notify the change in resource requirement + * for the codec component. + */ + private static final int CB_REQUIRED_RESOURCES_CHANGE = 9; + private class EventHandler extends Handler { private MediaCodec mCodec; @@ -2017,13 +2025,19 @@ final public class MediaCodec { case CB_METRICS_FLUSHED: { - if (GetFlag(() -> android.media.codec.Flags.subsessionMetrics())) { mCallback.onMetricsFlushed(mCodec, (PersistableBundle)msg.obj); } break; } + case CB_REQUIRED_RESOURCES_CHANGE: { + if (android.media.codec.Flags.codecAvailability()) { + mCallback.onRequiredResourcesChanged(mCodec); + } + break; + } + default: { break; @@ -2302,6 +2316,70 @@ final public class MediaCodec { } /** + * @hide + * Abstraction for the Global Codec resources. + * This encapsulates all the available codec resources on the device. + * + * To be able to enforce and test the implementation of codec availability hal APIs, + * globally available codec resources are exposed only as TestApi. + * This will be tracked and verified through cts. + */ + @FlaggedApi(FLAG_CODEC_AVAILABILITY) + @TestApi + public static final class GlobalResourceInfo { + /** + * Identifier for the Resource type. + */ + String mName; + /** + * Total count/capacity of resources of this type. + */ + long mCapacity; + /** + * Available count of this resource type. + */ + long mAvailable; + + @NonNull + public String getName() { + return mName; + } + + public long getCapacity() { + return mCapacity; + } + + public long getAvailable() { + return mAvailable; + } + }; + + /** + * @hide + * Get a list of globally available codec resources. + * + * To be able to enforce and test the implementation of codec availability hal APIs, + * it is exposed only as TestApi. + * This will be tracked and verified through cts. + * + * This returns a {@link java.util.List} list of codec resources. + * For every {@link GlobalResourceInfo} in the list, it encapsulates the + * information about each resources available globaly on device. + * + * @return A list of available device codec resources; an empty list if no + * device codec resources are available. + * @throws UnsupportedOperationException if not implemented. + */ + @FlaggedApi(FLAG_CODEC_AVAILABILITY) + @TestApi + public static @NonNull List<GlobalResourceInfo> getGloballyAvailableResources() { + return native_getGloballyAvailableResources(); + } + + @NonNull + private static native List<GlobalResourceInfo> native_getGloballyAvailableResources(); + + /** * Configures a component. * * @param format The format of the input data (decoder) or the desired @@ -2443,6 +2521,73 @@ final public class MediaCodec { } /** + * @hide + * Abstraction for the resources associated with a codec instance. + * This encapsulates the required codec resources for a configured codec instance. + * + * To be able to enforce and test the implementation of codec availability hal APIs, + * required codec resources are exposed only as TestApi. + * This will be tracked and verified through cts. + */ + @FlaggedApi(FLAG_CODEC_AVAILABILITY) + @TestApi + public static final class InstanceResourceInfo { + /** + * Identifier for the Resource type. + */ + String mName; + /** + * Required resource count of this type. + */ + long mStaticCount; + /** + * Per frame resource requirement of this resource type. + */ + long mPerFrameCount; + + @NonNull + public String getName() { + return mName; + } + + public long getStaticCount() { + return mStaticCount; + } + + public long getPerFrameCount() { + return mPerFrameCount; + } + }; + + /** + * @hide + * Get a list of required codec resources for this configuration. + * + * To be able to enforce and test the implementation of codec availability hal APIs, + * it is exposed only as TestApi. + * This will be tracked and verified through cts. + * + * This returns a {@link java.util.List} list of codec resources. + * For every {@link GlobalResourceInfo} in the list, it encapsulates the + * information about each resources required for the current configuration. + * + * NOTE: This may only be called after {@link #configure}. + * + * @return A list of required device codec resources; an empty list if no + * device codec resources are required. + * @throws IllegalStateException if the codec wasn't configured yet. + * @throws UnsupportedOperationException if not implemented. + */ + @FlaggedApi(FLAG_CODEC_AVAILABILITY) + @TestApi + public @NonNull List<InstanceResourceInfo> getRequiredResources() { + return native_getRequiredResources(); + } + + @NonNull + private native List<InstanceResourceInfo> native_getRequiredResources(); + + /** * Dynamically sets the output surface of a codec. * <p> * This can only be used if the codec was configured with an output surface. The @@ -5740,6 +5885,25 @@ final public class MediaCodec { @NonNull MediaCodec codec, @NonNull PersistableBundle metrics) { // default implementation ignores this callback. } + + /** + * @hide + * Called when there is a change in the required resources for the codec. + * <p> + * Upon receiving this notification, the updated resource requirement + * can be queried through {@link #getRequiredResources}. + * + * @param codec The MediaCodec object. + */ + @FlaggedApi(FLAG_CODEC_AVAILABILITY) + @TestApi + public void onRequiredResourcesChanged(@NonNull MediaCodec codec) { + /* + * A default implementation for backward compatibility. + * Since this is a TestApi, we are not enforcing the callback to be + * overridden. + */ + } } private void postEventFromNative( diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java index 96edd63a9b12..782db358bf9f 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -1876,6 +1876,8 @@ public final class MediaCodecInfo { * Codecs with this security model is not included in * {@link MediaCodecList#REGULAR_CODECS}, but included in * {@link MediaCodecList#ALL_CODECS}. + * + * @hide */ @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) public static final int SECURITY_MODEL_TRUSTED_CONTENT_ONLY = 2; diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java index bd65b2ecb76a..bc09aee9ac11 100644 --- a/media/java/android/media/MediaFormat.java +++ b/media/java/android/media/MediaFormat.java @@ -1748,6 +1748,7 @@ public final class MediaFormat { (1 << MediaCodecInfo.SECURITY_MODEL_MEMORY_SAFE); /** * Flag for {@link MediaCodecInfo#SECURITY_MODEL_TRUSTED_CONTENT_ONLY}. + * @hide */ @FlaggedApi(FLAG_IN_PROCESS_SW_AUDIO_CODEC) public static final int FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY = @@ -1759,8 +1760,7 @@ public final class MediaFormat { * The associated value is a flag of the following values: * {@link FLAG_SECURITY_MODEL_SANDBOXED}, * {@link FLAG_SECURITY_MODEL_MEMORY_SAFE}, - * {@link FLAG_SECURITY_MODEL_TRUSTED_CONTENT_ONLY}. The default value is - * {@link FLAG_SECURITY_MODEL_SANDBOXED}. + * The default value is {@link FLAG_SECURITY_MODEL_SANDBOXED}. * <p> * When passed to {@link MediaCodecList#findDecoderForFormat} or * {@link MediaCodecList#findEncoderForFormat}, MediaCodecList filters diff --git a/media/jni/Android.bp b/media/jni/Android.bp index 7f487e51f7e8..13dc748aa691 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -104,6 +104,7 @@ cc_library_shared { "libgrallocusage", "libmedia_midiiowrapper", "android.companion.virtualdevice.flags-aconfig-cc", + "android.media.codec-aconfig-cc", "android.media.playback.flags-aconfig-cc", ], diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp index 001653b08f0c..fc184fe5c872 100644 --- a/media/jni/android_media_MediaCodec.cpp +++ b/media/jni/android_media_MediaCodec.cpp @@ -39,6 +39,8 @@ #include <C2Buffer.h> #include <C2PlatformSupport.h> +#include <android_media_codec.h> + #include <android/hardware/cas/native/1.0/IDescrambler.h> #include <android_runtime/android_hardware_HardwareBuffer.h> @@ -189,6 +191,22 @@ static struct { jmethodID setId; } gBufferInfo; +static struct { + jclass clazz; + jmethodID ctorId; + jfieldID resourceId; + jfieldID capacityId; + jfieldID availableId; +} gGlobalResourceInfo; + +static struct { + jclass clazz; + jmethodID ctorId; + jfieldID resourceId; + jfieldID staticCountId; + jfieldID perFrameCountId; +} gInstanceResourceInfo; + struct fields_t { jmethodID postEventFromNativeID; jmethodID lockAndGetContextID; @@ -1129,6 +1147,37 @@ status_t JMediaCodec::unsubscribeFromVendorParameters(JNIEnv *env, jobject names return mCodec->unsubscribeFromVendorParameters(names); } +static jobject getJavaResources( + JNIEnv *env, + const std::vector<MediaCodec::InstanceResourceInfo>& resources) { + jobject resourcesObj = env->NewObject(gArrayListInfo.clazz, gArrayListInfo.ctorId); + for (const MediaCodec::InstanceResourceInfo& res : resources) { + ScopedLocalRef<jobject> object{env, env->NewObject( + gInstanceResourceInfo.clazz, gInstanceResourceInfo.ctorId)}; + ScopedLocalRef<jstring> nameStr{env, env->NewStringUTF(res.mName.c_str())}; + env->SetObjectField(object.get(), gInstanceResourceInfo.resourceId, nameStr.get()); + env->SetLongField(object.get(), + gInstanceResourceInfo.staticCountId, + (jlong)res.mStaticCount); + env->SetLongField(object.get(), + gInstanceResourceInfo.perFrameCountId, + (jlong)res.mPerFrameCount); + (void)env->CallBooleanMethod(resourcesObj, gArrayListInfo.addId, object.get()); + } + + return resourcesObj; +} + +status_t JMediaCodec::getRequiredResources(JNIEnv *env, jobject *resourcesObj) { + std::vector<MediaCodec::InstanceResourceInfo> resources; + status_t status = mCodec->getRequiredResources(resources); + if (status != OK) { + return status; + } + *resourcesObj = getJavaResources(env, resources); + return OK; +} + static jthrowable createCodecException( JNIEnv *env, status_t err, int32_t actionCode, const char *msg = NULL) { ScopedLocalRef<jclass> clazz( @@ -1475,6 +1524,10 @@ void JMediaCodec::handleCallback(const sp<AMessage> &msg) { obj = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL); break; } + case MediaCodec::CB_REQUIRED_RESOURCES_CHANGED: + { + break; + } default: TRESPASS(); @@ -3560,6 +3613,64 @@ static void android_media_MediaCodec_unsubscribeFromVendorParameters( return; } +static jobject getJavaResources( + JNIEnv *env, + const std::vector<MediaCodec::GlobalResourceInfo>& resources) { + jobject resourcesObj = env->NewObject(gArrayListInfo.clazz, gArrayListInfo.ctorId); + for (const MediaCodec::GlobalResourceInfo& res : resources) { + ScopedLocalRef<jobject> object{env, env->NewObject( + gGlobalResourceInfo.clazz, gGlobalResourceInfo.ctorId)}; + ScopedLocalRef<jstring> nameStr{env, env->NewStringUTF(res.mName.c_str())}; + env->SetObjectField(object.get(), gInstanceResourceInfo.resourceId, nameStr.get()); + env->SetLongField(object.get(), gGlobalResourceInfo.capacityId, (jlong)res.mCapacity); + env->SetLongField(object.get(), gGlobalResourceInfo.availableId, (jlong)res.mAvailable); + (void)env->CallBooleanMethod(resourcesObj, gArrayListInfo.addId, object.get()); + } + + return resourcesObj; +} + +static jobject android_media_MediaCodec_getGloballyAvailableResources( + JNIEnv *env, jobject thiz) { + (void)thiz; + std::vector<MediaCodec::GlobalResourceInfo> resources; + status_t status = MediaCodec::getGloballyAvailableResources(resources); + if (status != OK) { + if (status == ERROR_UNSUPPORTED) { + jniThrowException(env, "java/lang/UnsupportedOperationException", + "Function Not Implemented"); + } else { + throwExceptionAsNecessary(env, status, nullptr); + } + return nullptr; + } + + return getJavaResources(env, resources); +} + +static jobject android_media_MediaCodec_getRequiredResources( + JNIEnv *env, jobject thiz) { + sp<JMediaCodec> codec = getMediaCodec(env, thiz); + if (codec == nullptr || codec->initCheck() != OK) { + throwExceptionAsNecessary(env, INVALID_OPERATION, codec); + return nullptr; + } + + jobject ret = nullptr; + status_t status = codec->getRequiredResources(env, &ret); + if (status != OK) { + if (status == ERROR_UNSUPPORTED) { + jniThrowException(env, "java/lang/UnsupportedOperationException", + "Function Not Implemented"); + } else { + throwExceptionAsNecessary(env, status, nullptr); + } + return nullptr; + } + + return ret; +} + static void android_media_MediaCodec_native_init(JNIEnv *env, jclass) { ScopedLocalRef<jclass> clazz( env, env->FindClass("android/media/MediaCodec")); @@ -3905,6 +4016,36 @@ static void android_media_MediaCodec_native_init(JNIEnv *env, jclass) { gFields.bufferInfoOffset = env->GetFieldID(clazz.get(), "offset", "I"); gFields.bufferInfoPresentationTimeUs = env->GetFieldID(clazz.get(), "presentationTimeUs", "J"); + + // Since these TestApis are defined under the flag, make sure they are + // accessed only when the flag is set. + if (android::media::codec::codec_availability()) { + clazz.reset(env->FindClass("android/media/MediaCodec$GlobalResourceInfo")); + CHECK(clazz.get() != NULL); + gGlobalResourceInfo.clazz = (jclass)env->NewGlobalRef(clazz.get()); + gGlobalResourceInfo.ctorId = env->GetMethodID(clazz.get(), "<init>", "()V"); + CHECK(gGlobalResourceInfo.ctorId != NULL); + gGlobalResourceInfo.resourceId = + env->GetFieldID(clazz.get(), "mName", "Ljava/lang/String;"); + CHECK(gGlobalResourceInfo.resourceId != NULL); + gGlobalResourceInfo.capacityId = env->GetFieldID(clazz.get(), "mCapacity", "J"); + CHECK(gGlobalResourceInfo.capacityId != NULL); + gGlobalResourceInfo.availableId = env->GetFieldID(clazz.get(), "mAvailable", "J"); + CHECK(gGlobalResourceInfo.availableId != NULL); + + clazz.reset(env->FindClass("android/media/MediaCodec$InstanceResourceInfo")); + CHECK(clazz.get() != NULL); + gInstanceResourceInfo.clazz = (jclass)env->NewGlobalRef(clazz.get()); + gInstanceResourceInfo.ctorId = env->GetMethodID(clazz.get(), "<init>", "()V"); + CHECK(gInstanceResourceInfo.ctorId != NULL); + gInstanceResourceInfo.resourceId = + env->GetFieldID(clazz.get(), "mName", "Ljava/lang/String;"); + CHECK(gInstanceResourceInfo.resourceId != NULL); + gInstanceResourceInfo.staticCountId= env->GetFieldID(clazz.get(), "mStaticCount", "J"); + CHECK(gInstanceResourceInfo.staticCountId != NULL); + gInstanceResourceInfo.perFrameCountId = env->GetFieldID(clazz.get(), "mPerFrameCount", "J"); + CHECK(gInstanceResourceInfo.perFrameCountId != NULL); + } } static void android_media_MediaCodec_native_setup( @@ -4261,6 +4402,12 @@ static const JNINativeMethod gMethods[] = { { "native_finalize", "()V", (void *)android_media_MediaCodec_native_finalize }, + + { "native_getGloballyAvailableResources", "()Ljava/util/List;", + (void *)android_media_MediaCodec_getGloballyAvailableResources}, + + { "native_getRequiredResources", "()Ljava/util/List;", + (void *)android_media_MediaCodec_getRequiredResources}, }; static const JNINativeMethod gLinearBlockMethods[] = { diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h index c9b6b7f6f337..930dbbeb7f30 100644 --- a/media/jni/android_media_MediaCodec.h +++ b/media/jni/android_media_MediaCodec.h @@ -185,6 +185,8 @@ struct JMediaCodec : public AHandler { status_t unsubscribeFromVendorParameters(JNIEnv *env, jobject names); + status_t getRequiredResources(JNIEnv *env, jobject *resourcesObj); + bool hasCryptoOrDescrambler() { return mHasCryptoOrDescrambler; } const sp<ICrypto> &getCrypto() { return mCrypto; } diff --git a/native/graphics/jni/Android.bp b/native/graphics/jni/Android.bp index 0fb3049f63d8..962f54d6a23f 100644 --- a/native/graphics/jni/Android.bp +++ b/native/graphics/jni/Android.bp @@ -45,8 +45,10 @@ cc_library_shared { header_libs: [ "jni_headers", + "native_headers", "libhwui_internal_headers", ], + export_header_lib_headers: ["native_headers"], static_libs: ["libarect"], diff --git a/nfc/api/current.txt b/nfc/api/current.txt index 008120429c40..9a7a39f213ee 100644 --- a/nfc/api/current.txt +++ b/nfc/api/current.txt @@ -81,11 +81,14 @@ package android.nfc { method @FlaggedApi("android.nfc.enable_nfc_reader_option") public boolean isReaderOptionSupported(); method public boolean isSecureNfcEnabled(); method public boolean isSecureNfcSupported(); + method @FlaggedApi("android.nfc.nfc_check_tag_intent_preference") public boolean isTagIntentAllowed(); + method @FlaggedApi("android.nfc.nfc_check_tag_intent_preference") public boolean isTagIntentAppPreferenceSupported(); method @FlaggedApi("android.nfc.enable_nfc_charging") public boolean isWlcEnabled(); method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void resetDiscoveryTechnology(@NonNull android.app.Activity); method @FlaggedApi("android.nfc.enable_nfc_set_discovery_tech") public void setDiscoveryTechnology(@NonNull android.app.Activity, int, int); method @FlaggedApi("android.nfc.nfc_observe_mode") public boolean setObserveModeEnabled(boolean); field public static final String ACTION_ADAPTER_STATE_CHANGED = "android.nfc.action.ADAPTER_STATE_CHANGED"; + field @FlaggedApi("android.nfc.nfc_check_tag_intent_preference") public static final String ACTION_CHANGE_TAG_INTENT_PREFERENCE = "android.nfc.action.CHANGE_TAG_INTENT_PREFERENCE"; field public static final String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED"; field @RequiresPermission(android.Manifest.permission.NFC_PREFERRED_PAYMENT_INFO) public static final String ACTION_PREFERRED_PAYMENT_CHANGED = "android.nfc.action.PREFERRED_PAYMENT_CHANGED"; field public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; diff --git a/nfc/api/system-current.txt b/nfc/api/system-current.txt index a23845fa17e9..15814edcd86a 100644 --- a/nfc/api/system-current.txt +++ b/nfc/api/system-current.txt @@ -11,7 +11,6 @@ package android.nfc { method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.Map<java.lang.String,java.lang.Boolean> getTagIntentAppPreferenceForUser(int); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOn(); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public boolean isControllerAlwaysOnSupported(); - method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public boolean isTagIntentAppPreferenceSupported(); method @RequiresPermission(android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON) public void registerControllerAlwaysOnListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.ControllerAlwaysOnListener); method @FlaggedApi("android.nfc.nfc_vendor_cmd") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void registerNfcVendorNciCallback(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.NfcVendorNciCallback); method @FlaggedApi("android.nfc.enable_nfc_charging") public void registerWlcStateListener(@NonNull java.util.concurrent.Executor, @NonNull android.nfc.NfcAdapter.WlcStateListener); @@ -57,6 +56,7 @@ package android.nfc { @FlaggedApi("android.nfc.nfc_oem_extension") public final class NfcOemExtension { method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearPreference(); + method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int forceRoutingTableCommit(); method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull public java.util.List<java.lang.String> getActiveNfceeList(); method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.nfc.RoutingStatus getRoutingStatus(); method @FlaggedApi("android.nfc.nfc_oem_extension") @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public java.util.List<android.nfc.NfcRoutingTableEntry> getRoutingTable(); @@ -73,6 +73,9 @@ package android.nfc { method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void synchronizeScreenState(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void triggerInitialization(); method @FlaggedApi("android.nfc.nfc_oem_extension") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void unregisterCallback(@NonNull android.nfc.NfcOemExtension.Callback); + field public static final int COMMIT_ROUTING_STATUS_FAILED = 3; // 0x3 + field public static final int COMMIT_ROUTING_STATUS_FAILED_UPDATE_IN_PROGRESS = 6; // 0x6 + field public static final int COMMIT_ROUTING_STATUS_OK = 0; // 0x0 field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int DISABLE = 0; // 0x0 field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int ENABLE_DEFAULT = 1; // 0x1 field @FlaggedApi("android.nfc.nfc_oem_extension") public static final int ENABLE_EE = 3; // 0x3 @@ -89,13 +92,15 @@ package android.nfc { method public void onBootFinished(int); method public void onBootStarted(); method public void onCardEmulationActivated(boolean); - method public void onDisable(@NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onDisableFinished(int); + method public void onDisableRequested(@NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onDisableStarted(); method public void onEeListenActivated(boolean); - method public void onEnable(@NonNull java.util.function.Consumer<java.lang.Boolean>); + method public void onEeUpdated(); method public void onEnableFinished(int); + method public void onEnableRequested(@NonNull java.util.function.Consumer<java.lang.Boolean>); method public void onEnableStarted(); + method public void onExtractOemPackages(@NonNull android.nfc.NdefMessage, @NonNull java.util.function.Consumer<java.util.List<java.lang.String>>); method public void onGetOemAppSearchIntent(@NonNull java.util.List<java.lang.String>, @NonNull java.util.function.Consumer<android.content.Intent>); method public void onHceEventReceived(int); method public void onLaunchHceAppChooserActivity(@NonNull String, @NonNull java.util.List<android.nfc.cardemulation.ApduServiceInfo>, @NonNull android.content.ComponentName, @NonNull String); @@ -106,7 +111,8 @@ package android.nfc { method public void onReaderOptionChanged(boolean); method public void onRfDiscoveryStarted(boolean); method public void onRfFieldActivated(boolean); - method public void onRoutingChanged(); + method public void onRoutingChanged(@NonNull java.util.function.Consumer<java.lang.Boolean>); + method public void onRoutingTableFull(); method public void onStateUpdated(int); method public void onTagConnected(boolean); method public void onTagDispatch(@NonNull java.util.function.Consumer<java.lang.Boolean>); @@ -182,6 +188,12 @@ package android.nfc.cardemulation { method @FlaggedApi("android.nfc.enable_nfc_mainline") @NonNull public java.util.List<android.nfc.cardemulation.ApduServiceInfo> getServices(@NonNull String, int); method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void overrideRoutingTable(@NonNull android.app.Activity, int, int); method @FlaggedApi("android.nfc.nfc_override_recover_routing_table") public void recoverRoutingTable(@NonNull android.app.Activity); + method @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public int setServiceEnabledForCategoryOther(@NonNull android.content.ComponentName, boolean); + field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_ALREADY_SET = 3; // 0x3 + field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_FEATURE_UNSUPPORTED = 1; // 0x1 + field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_INVALID_SERVICE = 2; // 0x2 + field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_UNKNOWN_ERROR = 4; // 0x4 + field @FlaggedApi("android.nfc.nfc_set_service_enabled_for_category_other") public static final int SET_SERVICE_ENABLED_STATUS_OK = 0; // 0x0 } } diff --git a/nfc/java/android/nfc/INfcAdapter.aidl b/nfc/java/android/nfc/INfcAdapter.aidl index 40fd0683f465..a08b55fe86b8 100644 --- a/nfc/java/android/nfc/INfcAdapter.aidl +++ b/nfc/java/android/nfc/INfcAdapter.aidl @@ -120,4 +120,6 @@ interface INfcAdapter boolean isTagPresent(); List<Entry> getRoutingTableEntryList(); void indicateDataMigration(boolean inProgress, String pkg); + int commitRouting(); + boolean isTagIntentAllowed(in String pkg, in int Userid); } diff --git a/nfc/java/android/nfc/INfcCardEmulation.aidl b/nfc/java/android/nfc/INfcCardEmulation.aidl index 5e2e92d958a4..633d8bfbbb67 100644 --- a/nfc/java/android/nfc/INfcCardEmulation.aidl +++ b/nfc/java/android/nfc/INfcCardEmulation.aidl @@ -47,7 +47,7 @@ interface INfcCardEmulation boolean unsetPreferredService(); boolean supportsAidPrefixRegistration(); ApduServiceInfo getPreferredPaymentService(int userHandle); - boolean setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status); + int setServiceEnabledForCategoryOther(int userHandle, in ComponentName app, boolean status); boolean isDefaultPaymentRegistered(); void overrideRoutingTable(int userHandle, String protocol, String technology, in String pkg); diff --git a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl index b102e873d737..e5eac0b4d6fd 100644 --- a/nfc/java/android/nfc/INfcOemExtensionCallback.aidl +++ b/nfc/java/android/nfc/INfcOemExtensionCallback.aidl @@ -41,16 +41,19 @@ interface INfcOemExtensionCallback { void onEnableFinished(int status); void onDisableFinished(int status); void onTagDispatch(in ResultReceiver isSkipped); - void onRoutingChanged(); + void onRoutingChanged(in ResultReceiver isSkipped); void onHceEventReceived(int action); void onReaderOptionChanged(boolean enabled); void onCardEmulationActivated(boolean isActivated); void onRfFieldActivated(boolean isActivated); void onRfDiscoveryStarted(boolean isDiscoveryStarted); void onEeListenActivated(boolean isActivated); + void onEeUpdated(); void onGetOemAppSearchIntent(in List<String> firstPackage, in ResultReceiver intentConsumer); void onNdefMessage(in Tag tag, in NdefMessage message, in ResultReceiver hasOemExecutableContent); void onLaunchHceAppChooserActivity(in String selectedAid, in List<ApduServiceInfo> services, in ComponentName failedComponent, in String category); void onLaunchHceTapAgainActivity(in ApduServiceInfo service, in String category); + void onRoutingTableFull(); void onLogEventNotified(in OemLogItems item); + void onExtractOemPackages(in NdefMessage message, in ResultReceiver packageReceiver); } diff --git a/nfc/java/android/nfc/NfcAdapter.java b/nfc/java/android/nfc/NfcAdapter.java index c5d8191b22e6..056844f38f3c 100644 --- a/nfc/java/android/nfc/NfcAdapter.java +++ b/nfc/java/android/nfc/NfcAdapter.java @@ -49,6 +49,7 @@ import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; +import android.os.UserHandle; import android.util.Log; import java.io.IOException; @@ -2505,22 +2506,22 @@ public final class NfcAdapter { } /** - * Checks if the device supports Tag application preference. + * Checks if the device supports Tag Intent App Preference functionality. + * + * When supported, {@link #ACTION_NDEF_DISCOVERED}, {@link #ACTION_TECH_DISCOVERED} or + * {@link #ACTION_TAG_DISCOVERED} will not be dispatched to an Activity if + * {@link isTagIntentAllowed} returns {@code false}. * * @return {@code true} if the device supports Tag application preference, {@code false} * otherwise * @throws UnsupportedOperationException if FEATURE_NFC is unavailable - * - * @hide */ - @SystemApi - @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + @FlaggedApi(Flags.FLAG_NFC_CHECK_TAG_INTENT_PREFERENCE) public boolean isTagIntentAppPreferenceSupported() { if (!sHasNfcFeature) { throw new UnsupportedOperationException(); } return callServiceReturn(() -> sService.isTagIntentAppPreferenceSupported(), false); - } /** @@ -2895,4 +2896,42 @@ public final class NfcAdapter { } return mNfcOemExtension; } + + /** + * Activity action: Bring up the settings page that allows the user to enable or disable tag + * intent reception for apps. + * + * <p>This will direct user to the settings page shows a list that asks users whether + * they want to allow or disallow the package to start an activity when a tag is discovered. + * + */ + @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) + @FlaggedApi(Flags.FLAG_NFC_CHECK_TAG_INTENT_PREFERENCE) + public static final String ACTION_CHANGE_TAG_INTENT_PREFERENCE = + "android.nfc.action.CHANGE_TAG_INTENT_PREFERENCE"; + + /** + * Checks whether the user has disabled the calling app from receiving NFC tag intents. + * + * <p>This method checks whether the caller package name is either not present in the user + * disabled list or is explicitly allowed by the user. + * + * @return {@code true} if an app is either not present in the list or is added to the list + * with the flag set to {@code true}. Otherwise, it returns {@code false}. + * It also returns {@code true} if {@link isTagIntentAppPreferenceSupported} returns + * {@code false}. + * + * @throws UnsupportedOperationException if FEATURE_NFC is unavailable. + */ + @FlaggedApi(Flags.FLAG_NFC_CHECK_TAG_INTENT_PREFERENCE) + public boolean isTagIntentAllowed() { + if (!sHasNfcFeature) { + throw new UnsupportedOperationException(); + } + if (!isTagIntentAppPreferenceSupported()) { + return true; + } + return callServiceReturn(() -> sService.isTagIntentAllowed(mContext.getPackageName(), + UserHandle.myUserId()), false); + } } diff --git a/nfc/java/android/nfc/NfcOemExtension.java b/nfc/java/android/nfc/NfcOemExtension.java index abd99bc02f55..9ed678fe6014 100644 --- a/nfc/java/android/nfc/NfcOemExtension.java +++ b/nfc/java/android/nfc/NfcOemExtension.java @@ -23,11 +23,11 @@ import static android.nfc.cardemulation.CardEmulation.routeIntToString; import android.Manifest; import android.annotation.CallbackExecutor; +import android.annotation.DurationMillisLong; import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.RequiresPermission; -import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.content.ComponentName; import android.content.Context; @@ -194,6 +194,30 @@ public final class NfcOemExtension { public @interface StatusCode {} /** + * Routing commit succeeded. + */ + public static final int COMMIT_ROUTING_STATUS_OK = 0; + /** + * Routing commit failed. + */ + public static final int COMMIT_ROUTING_STATUS_FAILED = 3; + /** + * Routing commit failed due to the update is in progress. + */ + public static final int COMMIT_ROUTING_STATUS_FAILED_UPDATE_IN_PROGRESS = 6; + + /** + * Status codes returned when calling {@link #forceRoutingTableCommit()} + * @hide + */ + @IntDef(prefix = "COMMIT_ROUTING_STATUS_", value = { + COMMIT_ROUTING_STATUS_OK, + COMMIT_ROUTING_STATUS_FAILED, + COMMIT_ROUTING_STATUS_FAILED_UPDATE_IN_PROGRESS, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface CommitRoutingStatusCode {} + /** * Interface for Oem extensions for NFC. */ public interface Callback { @@ -233,8 +257,7 @@ public final class NfcOemExtension { * {@link Boolean#TRUE}, otherwise call with {@link Boolean#FALSE}. * false if NFC cannot be enabled at this time. */ - @SuppressLint("MethodNameTense") - void onEnable(@NonNull Consumer<Boolean> isAllowed); + void onEnableRequested(@NonNull Consumer<Boolean> isAllowed); /** * Method to check if Nfc is allowed to be disabled by OEMs. * @param isAllowed The {@link Consumer} to be completed. If disabling NFC is allowed, @@ -242,7 +265,7 @@ public final class NfcOemExtension { * {@link Boolean#TRUE}, otherwise call with {@link Boolean#FALSE}. * false if NFC cannot be disabled at this time. */ - void onDisable(@NonNull Consumer<Boolean> isAllowed); + void onDisableRequested(@NonNull Consumer<Boolean> isAllowed); /** * Callback to indicate that Nfc starts to boot. @@ -255,7 +278,7 @@ public final class NfcOemExtension { void onEnableStarted(); /** - * Callback to indicate that Nfc starts to enable. + * Callback to indicate that Nfc starts to disable. */ void onDisableStarted(); @@ -287,8 +310,12 @@ public final class NfcOemExtension { /** * Notifies routing configuration is changed. + * @param isCommitRoutingSkipped The {@link Consumer} to be + * completed. If routing commit should be skipped, + * the {@link Consumer#accept(Object)} should be called with + * {@link Boolean#TRUE}, otherwise call with {@link Boolean#FALSE}. */ - void onRoutingChanged(); + void onRoutingChanged(@NonNull Consumer<Boolean> isCommitRoutingSkipped); /** * API to activate start stop cpu boost on hce event. @@ -340,6 +367,15 @@ public final class NfcOemExtension { void onEeListenActivated(boolean isActivated); /** + * Notifies that some NFCEE (NFC Execution Environment) has been updated. + * + * <p> This indicates that some applet has been installed/updated/removed in + * one of the NFCEE's. + * </p> + */ + void onEeUpdated(); + + /** * Gets the intent to find the OEM package in the OEM App market. If the consumer returns * {@code null} or a timeout occurs, the intent from the first available package will be * used instead. @@ -394,10 +430,30 @@ public final class NfcOemExtension { void onLaunchHceTapAgainDialog(@NonNull ApduServiceInfo service, @NonNull String category); /** + * Callback to indicate that routing table is full and the OEM can optionally launch a + * dialog to request the user to remove some Card Emulation apps from the device to free + * routing table space. + */ + void onRoutingTableFull(); + + /** * Callback when OEM specified log event are notified. * @param item the log items that contains log information of NFC event. */ void onLogEventNotified(@NonNull OemLogItems item); + + /** + * Callback to to extract OEM defined packages from given NDEF message when + * a NFC tag is detected. These are used to handle NFC tags encoded with a + * proprietary format for storing app name (Android native app format). + * + * @param message NDEF message containing OEM package names + * @param packageConsumer The {@link Consumer} to be completed. + * The {@link Consumer#accept(Object)} should be called with + * the list of package names. + */ + void onExtractOemPackages(@NonNull NdefMessage message, + @NonNull Consumer<List<String>> packageConsumer); } @@ -598,12 +654,12 @@ public final class NfcOemExtension { /** * Pauses NFC tag reader mode polling for a {@code timeoutInMs} millisecond. * In case of {@code timeoutInMs} is zero or invalid polling will be stopped indefinitely - * use {@link #resumePolling() to resume the polling. - * @param timeoutInMs the pause polling duration in millisecond + * use {@link #resumePolling()} to resume the polling. + * @param timeoutInMs the pause polling duration in millisecond, ranging from 0 to 40000. */ @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) - public void pausePolling(int timeoutInMs) { + public void pausePolling(@DurationMillisLong int timeoutInMs) { NfcAdapter.callService(() -> NfcAdapter.sService.pausePolling(timeoutInMs)); } @@ -734,6 +790,18 @@ public final class NfcOemExtension { return result; } + /** + * API to force a routing table commit. + * @return a {@link StatusCode} to indicate if commit routing succeeded or not + */ + @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) + @FlaggedApi(Flags.FLAG_NFC_OEM_EXTENSION) + @CommitRoutingStatusCode + public int forceRoutingTableCommit() { + return NfcAdapter.callServiceReturn( + () -> NfcAdapter.sService.commitRouting(), COMMIT_ROUTING_STATUS_FAILED); + } + private final class NfcOemExtensionCallback extends INfcOemExtensionCallback.Stub { @Override @@ -771,6 +839,12 @@ public final class NfcOemExtension { } @Override + public void onEeUpdated() throws RemoteException { + mCallbackMap.forEach((cb, ex) -> + handleVoidCallback(null, (Object input) -> cb.onEeUpdated(), ex)); + } + + @Override public void onStateUpdated(int state) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback(state, cb::onStateUpdated, ex)); @@ -792,13 +866,13 @@ public final class NfcOemExtension { public void onEnable(ResultReceiver isAllowed) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( - new ReceiverWrapper<>(isAllowed), cb::onEnable, ex)); + new ReceiverWrapper<>(isAllowed), cb::onEnableRequested, ex)); } @Override public void onDisable(ResultReceiver isAllowed) throws RemoteException { mCallbackMap.forEach((cb, ex) -> handleVoidCallback( - new ReceiverWrapper<>(isAllowed), cb::onDisable, ex)); + new ReceiverWrapper<>(isAllowed), cb::onDisableRequested, ex)); } @Override public void onBootStarted() throws RemoteException { @@ -837,9 +911,10 @@ public final class NfcOemExtension { new ReceiverWrapper<>(isSkipped), cb::onTagDispatch, ex)); } @Override - public void onRoutingChanged() throws RemoteException { + public void onRoutingChanged(ResultReceiver isSkipped) throws RemoteException { mCallbackMap.forEach((cb, ex) -> - handleVoidCallback(null, (Object input) -> cb.onRoutingChanged(), ex)); + handleVoidCallback( + new ReceiverWrapper<>(isSkipped), cb::onRoutingChanged, ex)); } @Override public void onHceEventReceived(int action) throws RemoteException { @@ -853,6 +928,12 @@ public final class NfcOemExtension { handleVoidCallback(enabled, cb::onReaderOptionChanged, ex)); } + public void onRoutingTableFull() throws RemoteException { + mCallbackMap.forEach((cb, ex) -> + handleVoidCallback(null, + (Object input) -> cb.onRoutingTableFull(), ex)); + } + @Override public void onGetOemAppSearchIntent(List<String> packages, ResultReceiver intentConsumer) throws RemoteException { @@ -912,6 +993,15 @@ public final class NfcOemExtension { handleVoidCallback(item, cb::onLogEventNotified, ex)); } + @Override + public void onExtractOemPackages(NdefMessage message, ResultReceiver packageConsumer) + throws RemoteException { + mCallbackMap.forEach((cb, ex) -> + handleVoid2ArgCallback(message, + new ReceiverWrapper<>(packageConsumer), + cb::onExtractOemPackages, ex)); + } + private <T> void handleVoidCallback( T input, Consumer<T> callbackMethod, Executor executor) { synchronized (mLock) { @@ -1022,8 +1112,14 @@ public final class NfcOemExtension { Bundle bundle = new Bundle(); bundle.putParcelable("intent", (Intent) result); mResultReceiver.send(0, bundle); + } else if (result instanceof List<?> list) { + if (list.stream().allMatch(String.class::isInstance)) { + Bundle bundle = new Bundle(); + bundle.putStringArray("packageNames", + list.stream().map(pkg -> (String) pkg).toArray(String[]::new)); + mResultReceiver.send(0, bundle); + } } - } @Override diff --git a/nfc/java/android/nfc/OemLogItems.java b/nfc/java/android/nfc/OemLogItems.java index 6671941c1cc9..4f3e1999f5d3 100644 --- a/nfc/java/android/nfc/OemLogItems.java +++ b/nfc/java/android/nfc/OemLogItems.java @@ -142,8 +142,11 @@ public final class OemLogItems implements Parcelable { dest.writeByteArray(mCommandApdus);
dest.writeInt(mResponseApdus.length);
dest.writeByteArray(mResponseApdus);
- dest.writeLong(mRfFieldOnTime.getEpochSecond());
- dest.writeInt(mRfFieldOnTime.getNano());
+ dest.writeBoolean(mRfFieldOnTime != null);
+ if (mRfFieldOnTime != null) {
+ dest.writeLong(mRfFieldOnTime.getEpochSecond());
+ dest.writeInt(mRfFieldOnTime.getNano());
+ }
dest.writeParcelable(mTag, 0);
}
@@ -305,7 +308,12 @@ public final class OemLogItems implements Parcelable { in.readByteArray(this.mCommandApdus);
this.mResponseApdus = new byte[in.readInt()];
in.readByteArray(this.mResponseApdus);
- this.mRfFieldOnTime = Instant.ofEpochSecond(in.readLong(), in.readInt());
+ boolean isRfFieldOnTimeSet = in.readBoolean();
+ if (isRfFieldOnTimeSet) {
+ this.mRfFieldOnTime = Instant.ofEpochSecond(in.readLong(), in.readInt());
+ } else {
+ this.mRfFieldOnTime = null;
+ }
this.mTag = in.readParcelable(Tag.class.getClassLoader(), Tag.class);
}
diff --git a/nfc/java/android/nfc/cardemulation/CardEmulation.java b/nfc/java/android/nfc/cardemulation/CardEmulation.java index eb28c3b9c930..891752475824 100644 --- a/nfc/java/android/nfc/cardemulation/CardEmulation.java +++ b/nfc/java/android/nfc/cardemulation/CardEmulation.java @@ -185,6 +185,65 @@ public final class CardEmulation { @FlaggedApi(Flags.FLAG_NFC_OVERRIDE_RECOVER_ROUTING_TABLE) public static final int PROTOCOL_AND_TECHNOLOGY_ROUTE_UNSET = -1; + /** + * Status code returned when {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)} + * succeeded. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER) + public static final int SET_SERVICE_ENABLED_STATUS_OK = 0; + + /** + * Status code returned when {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)} + * failed due to the unsupported feature. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER) + public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_FEATURE_UNSUPPORTED = 1; + + /** + * Status code returned when {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)} + * failed due to the invalid service. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER) + public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_INVALID_SERVICE = 2; + + /** + * Status code returned when {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)} + * failed due to the service is already set to the requested status. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER) + public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_ALREADY_SET = 3; + + /** + * Status code returned when {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)} + * failed due to unknown error. + * @hide + */ + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER) + public static final int SET_SERVICE_ENABLED_STATUS_FAILURE_UNKNOWN_ERROR = 4; + + /** + * Status code returned by {@link #setServiceEnabledForCategoryOther(ComponentName, boolean)} + * @hide + */ + @IntDef(prefix = "SET_SERVICE_ENABLED_STATUS_", value = { + SET_SERVICE_ENABLED_STATUS_OK, + SET_SERVICE_ENABLED_STATUS_FAILURE_FEATURE_UNSUPPORTED, + SET_SERVICE_ENABLED_STATUS_FAILURE_INVALID_SERVICE, + SET_SERVICE_ENABLED_STATUS_FAILURE_ALREADY_SET, + SET_SERVICE_ENABLED_STATUS_FAILURE_UNKNOWN_ERROR + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SetServiceEnabledStatusCode {} + static boolean sIsInitialized = false; static HashMap<Context, CardEmulation> sCardEmus = new HashMap<Context, CardEmulation>(); static INfcCardEmulation sService; @@ -883,22 +942,24 @@ public final class CardEmulation { } /** - * Allows to set or unset preferred service (category other) to avoid AID Collision. + * Allows to set or unset preferred service (category other) to avoid AID Collision. The user + * should use corresponding context using {@link Context#createContextAsUser(UserHandle, int)} * * @param service The ComponentName of the service * @param status true to enable, false to disable - * @param userId the user handle of the user whose information is being requested. - * @return set service for the category and true if service is already set return false. + * @return true if preferred service is successfully set or unset, otherwise return false. * * @hide */ - public boolean setServiceEnabledForCategoryOther(ComponentName service, boolean status, - int userId) { - if (service == null) { - throw new NullPointerException("activity or service or category is null"); - } + @SystemApi + @FlaggedApi(Flags.FLAG_NFC_SET_SERVICE_ENABLED_FOR_CATEGORY_OTHER) + @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) + @SetServiceEnabledStatusCode + public int setServiceEnabledForCategoryOther(@NonNull ComponentName service, + boolean status) { return callServiceReturn(() -> - sService.setServiceEnabledForCategoryOther(userId, service, status), false); + sService.setServiceEnabledForCategoryOther(mContext.getUser().getIdentifier(), + service, status), SET_SERVICE_ENABLED_STATUS_FAILURE_UNKNOWN_ERROR); } /** @hide */ diff --git a/nfc/java/android/nfc/flags.aconfig b/nfc/java/android/nfc/flags.aconfig index 34f020012d3c..ee287aba709f 100644 --- a/nfc/java/android/nfc/flags.aconfig +++ b/nfc/java/android/nfc/flags.aconfig @@ -173,3 +173,19 @@ flag { description: "Share wallet role routing priority with associated services" bug: "366243361" } + +flag { + name: "nfc_set_service_enabled_for_category_other" + is_exported: true + namespace: "nfc" + description: "Enable set service enabled for category other" + bug: "338157113" +} + +flag { + name: "nfc_check_tag_intent_preference" + is_exported: true + namespace: "nfc" + description: "App can check its tag intent preference status" + bug: "335916336" +} diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml index dd6545b24c07..06d451f6f8ab 100644 --- a/packages/SettingsLib/res/values/strings.xml +++ b/packages/SettingsLib/res/values/strings.xml @@ -821,9 +821,9 @@ <!-- Title of checkbox setting that enables the Linux terminal app. [CHAR LIMIT=32] --> <string name="enable_linux_terminal_title">Linux development environment</string> - <!-- Summary of checkbox setting that enables the Linux terminal app. [CHAR LIMIT=64] --> - <string name="enable_linux_terminal_summary">Run Linux terminal on Android</string> - <!-- Disclaimer below the checkbox that disabling the Linux terminal app would clear its data. [CHAR LIMIT=64] --> + <!-- Summary of checkbox setting that enables the Linux terminal app. [CHAR LIMIT=none] --> + <string name="enable_linux_terminal_summary">(Experimental) Run Linux terminal on Android</string> + <!-- Disclaimer below the checkbox that disabling the Linux terminal app would clear its data. [CHAR LIMIT=none] --> <string name="disable_linux_terminal_disclaimer">If you disable, Linux terminal data will be cleared</string> <!-- HDCP checking title, used for debug purposes only. [CHAR LIMIT=25] --> diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml index 18dd5c10384f..676ff97226ed 100644 --- a/packages/Shell/AndroidManifest.xml +++ b/packages/Shell/AndroidManifest.xml @@ -715,6 +715,9 @@ <uses-permission android:name="android.permission.UWB_PRIVILEGED" /> <uses-permission android:name="android.permission.UWB_RANGING" /> + <!-- Permission required for CTS test - CtsRangingTestCases --> + <uses-permission android:name="android.permission.RANGING" /> + <!-- Permission required for CTS test - CtsAlarmManagerTestCases --> <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" /> diff --git a/packages/Shell/OWNERS b/packages/Shell/OWNERS index 177f86b08864..c3ecff418075 100644 --- a/packages/Shell/OWNERS +++ b/packages/Shell/OWNERS @@ -11,3 +11,4 @@ patb@google.com cbrubaker@google.com omakoto@google.com michaelwr@google.com +ronish@google.com diff --git a/ravenwood/Framework.bp b/ravenwood/Framework.bp index d20773844df3..99fc31b258e9 100644 --- a/ravenwood/Framework.bp +++ b/ravenwood/Framework.bp @@ -214,7 +214,8 @@ java_genrule { java_genrule { name: "services.core.ravenwood", - defaults: ["ravenwood-internal-only-visibility-genrule"], + // This is used by unit tests too (so tests will be able to access HSG-processed implementation) + // so it's visible to all. cmd: "cp $(in) $(out)", srcs: [ ":services.core.ravenwood-base{ravenwood.jar}", diff --git a/ravenwood/TEST_MAPPING b/ravenwood/TEST_MAPPING index a1243e37003e..cb54e9f56c0c 100644 --- a/ravenwood/TEST_MAPPING +++ b/ravenwood/TEST_MAPPING @@ -113,11 +113,11 @@ "host": true }, { - "name": "FrameworksMockingServicesTestsRavenwood", + "name": "FrameworksServicesTestsRavenwood_Compat", "host": true }, { - "name": "FrameworksServicesTestsRavenwood", + "name": "FrameworksServicesTestsRavenwood_Uri", "host": true }, { diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java index 869d854f7b23..9b71f8050c80 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodAwareTestRunner.java @@ -30,6 +30,8 @@ import android.util.Log; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.ravenwood.common.RavenwoodCommonUtils; + import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runner.Runner; @@ -229,7 +231,9 @@ public final class RavenwoodAwareTestRunner extends RavenwoodAwareTestRunnerBase s.evaluate(); onAfter(description, scope, order, null); } catch (Throwable t) { - if (onAfter(description, scope, order, t)) { + var shouldReportFailure = RavenwoodCommonUtils.runIgnoringException( + () -> onAfter(description, scope, order, t)); + if (shouldReportFailure == null || shouldReportFailure) { throw t; } } diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java index c5a9c7b28ad3..1c1f15761329 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodRuntimeEnvironmentController.java @@ -22,6 +22,8 @@ import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_INST_R import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_RESOURCE_APK; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERBOSE_LOGGING; import static com.android.ravenwood.common.RavenwoodCommonUtils.RAVENWOOD_VERSION_JAVA_SYSPROP; +import static com.android.ravenwood.common.RavenwoodCommonUtils.parseNullableInt; +import static com.android.ravenwood.common.RavenwoodCommonUtils.withDefault; import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; @@ -30,17 +32,22 @@ import static org.mockito.Mockito.mock; import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.AppCompatCallbacks; import android.app.Instrumentation; import android.app.ResourcesManager; import android.app.UiAutomation; +import android.content.Context; +import android.content.pm.ApplicationInfo; import android.content.res.Resources; import android.os.Binder; import android.os.Build; +import android.os.Build.VERSION_CODES; import android.os.Bundle; import android.os.HandlerThread; import android.os.Looper; import android.os.Process_ravenwood; import android.os.ServiceManager; +import android.os.ServiceManager.ServiceNotFoundException; import android.os.SystemProperties; import android.provider.DeviceConfig_host; import android.system.ErrnoException; @@ -58,6 +65,7 @@ import com.android.ravenwood.common.RavenwoodCommonUtils; import com.android.ravenwood.common.RavenwoodRuntimeException; import com.android.ravenwood.common.SneakyThrow; import com.android.server.LocalServices; +import com.android.server.compat.PlatformCompat; import org.junit.runner.Description; @@ -149,6 +157,13 @@ public class RavenwoodRuntimeEnvironmentController { private static RavenwoodAwareTestRunner sRunner; private static RavenwoodSystemProperties sProps; + private static final int DEFAULT_TARGET_SDK_LEVEL = VERSION_CODES.CUR_DEVELOPMENT; + private static final String DEFAULT_PACKAGE_NAME = "com.android.ravenwoodtests.defaultname"; + + private static int sTargetSdkLevel; + private static String sTestPackageName; + private static String sTargetPackageName; + /** * Initialize the global environment. */ @@ -230,9 +245,22 @@ public class RavenwoodRuntimeEnvironmentController { System.setProperty("android.junit.runner", "androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner"); + loadRavenwoodProperties(); + assertMockitoVersion(); } + private static void loadRavenwoodProperties() { + var props = RavenwoodSystemProperties.readProperties("ravenwood.properties"); + + sTargetSdkLevel = withDefault( + parseNullableInt(props.get("targetSdkVersionInt")), DEFAULT_TARGET_SDK_LEVEL); + sTargetPackageName = withDefault(props.get("packageName"), DEFAULT_PACKAGE_NAME); + sTestPackageName = withDefault(props.get("instPackageName"), sTargetPackageName); + + // TODO(b/377765941) Read them from the manifest too? + } + /** * Initialize the environment. */ @@ -251,7 +279,9 @@ public class RavenwoodRuntimeEnvironmentController { initInner(runner.mState.getConfig()); } catch (Exception th) { Log.e(TAG, "init() failed", th); - reset(); + + RavenwoodCommonUtils.runIgnoringException(()-> reset()); + SneakyThrow.sneakyThrow(th); } } @@ -262,6 +292,14 @@ public class RavenwoodRuntimeEnvironmentController { Thread.setDefaultUncaughtExceptionHandler(sUncaughtExceptionHandler); } + config.mTargetPackageName = sTargetPackageName; + config.mTestPackageName = sTestPackageName; + config.mTargetSdkLevel = sTargetSdkLevel; + + Log.i(TAG, "TargetPackageName=" + sTargetPackageName); + Log.i(TAG, "TestPackageName=" + sTestPackageName); + Log.i(TAG, "TargetSdkLevel=" + sTargetSdkLevel); + RavenwoodRuntimeState.sUid = config.mUid; RavenwoodRuntimeState.sPid = config.mPid; RavenwoodRuntimeState.sTargetSdkLevel = config.mTargetSdkLevel; @@ -331,6 +369,8 @@ public class RavenwoodRuntimeEnvironmentController { RavenwoodSystemServer.init(config); + initializeCompatIds(config); + if (ENABLE_TIMEOUT_STACKS) { sPendingTimeout = sTimeoutExecutor.schedule( RavenwoodRuntimeEnvironmentController::dumpStacks, @@ -342,12 +382,43 @@ public class RavenwoodRuntimeEnvironmentController { * Partially re-initialize after each test method invocation */ public static void reinit() { - var config = sRunner.mState.getConfig(); - Binder.restoreCallingIdentity(packBinderIdentityToken(false, config.mUid, config.mPid)); + // sRunner could be null, if there was a failure in the initialization. + if (sRunner != null) { + var config = sRunner.mState.getConfig(); + Binder.restoreCallingIdentity(packBinderIdentityToken(false, config.mUid, config.mPid)); + } + } + + private static void initializeCompatIds(RavenwoodConfig config) { + // Set up compat-IDs for the app side. + // TODO: Inside the system server, all the compat-IDs should be enabled, + // Due to the `AppCompatCallbacks.install(new long[0], new long[0])` call in + // SystemServer. + + // Compat framework only uses the package name and the target SDK level. + ApplicationInfo appInfo = new ApplicationInfo(); + appInfo.packageName = config.mTargetPackageName; + appInfo.targetSdkVersion = config.mTargetSdkLevel; + + PlatformCompat platformCompat = null; + try { + platformCompat = (PlatformCompat) ServiceManager.getServiceOrThrow( + Context.PLATFORM_COMPAT_SERVICE); + } catch (ServiceNotFoundException e) { + throw new RuntimeException(e); + } + + var disabledChanges = platformCompat.getDisabledChanges(appInfo); + var loggableChanges = platformCompat.getLoggableChanges(appInfo); + + AppCompatCallbacks.install(disabledChanges, loggableChanges); } /** * De-initialize. + * + * Note, we call this method when init() fails too, so this method should deal with + * any partially-initialized states. */ public static void reset() { if (RAVENWOOD_VERBOSE_LOGGING) { @@ -379,7 +450,9 @@ public class RavenwoodRuntimeEnvironmentController { config.mState.mSystemServerContext.cleanUp(); } - Looper.getMainLooper().quit(); + if (Looper.getMainLooper() != null) { + Looper.getMainLooper().quit(); + } Looper.clearMainLooperForTest(); ActivityManager.reset$ravenwood(); diff --git a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java index f198a08a50e3..438a2bfa7a14 100644 --- a/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java +++ b/ravenwood/junit-impl-src/android/platform/test/ravenwood/RavenwoodSystemServer.java @@ -17,7 +17,9 @@ package android.platform.test.ravenwood; import android.content.ClipboardManager; +import android.content.Context; import android.hardware.SerialManager; +import android.os.ServiceManager; import android.os.SystemClock; import android.ravenwood.example.BlueManager; import android.ravenwood.example.RedManager; @@ -27,6 +29,8 @@ import android.util.ArraySet; import com.android.server.LocalServices; import com.android.server.SystemService; import com.android.server.SystemServiceManager; +import com.android.server.compat.PlatformCompat; +import com.android.server.compat.PlatformCompatNative; import com.android.server.utils.TimingsTraceAndSlog; import java.util.List; @@ -65,6 +69,14 @@ public class RavenwoodSystemServer { private static SystemServiceManager sServiceManager; public static void init(RavenwoodConfig config) { + // Always start PlatformCompat, regardless of the requested services. + // PlatformCompat is not really a SystemService, so it won't receive boot phases / etc. + // This initialization code is copied from SystemServer.java. + PlatformCompat platformCompat = new PlatformCompat(config.mState.mSystemServerContext); + ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat); + ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE, + new PlatformCompatNative(platformCompat)); + // Avoid overhead if no services required if (config.mServicesRequired.isEmpty()) return; diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java index 3ed8b0a748e1..619c8e30c78e 100644 --- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java +++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodConfig.java @@ -22,7 +22,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Instrumentation; import android.content.Context; -import android.os.Build; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -30,16 +29,12 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.concurrent.atomic.AtomicInteger; /** - * Represents how to configure the ravenwood environment for a test class. - * - * If a ravenwood test class has a public static field with the {@link Config} annotation, - * Ravenwood will extract the config from it and initializes the environment. The type of the - * field must be of {@link RavenwoodConfig}. + * @deprecated This class will be removed. Reach out to g/ravenwood if you need any features in it. */ +@Deprecated public final class RavenwoodConfig { /** * Use this to mark a field as the configuration. @@ -66,7 +61,7 @@ public final class RavenwoodConfig { String mTestPackageName; String mTargetPackageName; - int mTargetSdkLevel = Build.VERSION_CODES.CUR_DEVELOPMENT; + int mTargetSdkLevel; final RavenwoodSystemProperties mSystemProperties = new RavenwoodSystemProperties(); @@ -91,12 +86,6 @@ public final class RavenwoodConfig { return RavenwoodRule.isOnRavenwood(); } - private void setDefaults() { - if (mTargetPackageName == null) { - mTargetPackageName = mTestPackageName; - } - } - public static class Builder { private final RavenwoodConfig mConfig = new RavenwoodConfig(); @@ -120,28 +109,27 @@ public final class RavenwoodConfig { } /** - * Configure the package name of the test, which corresponds to - * {@link Instrumentation#getContext()}. + * @deprecated no longer used. Package name is set in the build file. (for now) */ + @Deprecated public Builder setPackageName(@NonNull String packageName) { - mConfig.mTestPackageName = Objects.requireNonNull(packageName); return this; } /** - * Configure the package name of the target app, which corresponds to - * {@link Instrumentation#getTargetContext()}. Defaults to {@link #setPackageName}. + * @deprecated no longer used. Package name is set in the build file. (for now) */ + @Deprecated public Builder setTargetPackageName(@NonNull String packageName) { - mConfig.mTargetPackageName = Objects.requireNonNull(packageName); return this; } + /** - * Configure the target SDK level of the test. + * @deprecated no longer used. Target SDK level is set in the build file. (for now) */ + @Deprecated public Builder setTargetSdkLevel(int sdkLevel) { - mConfig.mTargetSdkLevel = sdkLevel; return this; } @@ -205,7 +193,6 @@ public final class RavenwoodConfig { } public RavenwoodConfig build() { - mConfig.setDefaults(); return mConfig; } } diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java index bfa3802ce583..f7acd9022300 100644 --- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java +++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodRule.java @@ -36,10 +36,8 @@ import java.util.Objects; import java.util.regex.Pattern; /** - * @deprecated Use {@link RavenwoodConfig} to configure the ravenwood environment instead. - * A {@link RavenwoodRule} is no longer needed for {@link DisabledOnRavenwood}. To get the - * {@link Context} and {@link Instrumentation}, use - * {@link androidx.test.platform.app.InstrumentationRegistry} instead. + * @deprecated This class is undergoing a major change. Reach out to g/ravenwood if you need + * any featues in it. */ @Deprecated public final class RavenwoodRule implements TestRule { @@ -128,11 +126,10 @@ public final class RavenwoodRule implements TestRule { } /** - * Configure the identity of this process to be the given package name for the duration - * of the test. Has no effect on non-Ravenwood environments. + * @deprecated no longer used. */ + @Deprecated public Builder setPackageName(@NonNull String packageName) { - mBuilder.setPackageName(packageName); return this; } diff --git a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java index 3e4619f55c6d..9bd376a76f77 100644 --- a/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java +++ b/ravenwood/junit-src/android/platform/test/ravenwood/RavenwoodSystemProperties.java @@ -52,7 +52,7 @@ public class RavenwoodSystemProperties { "vendor_dlkm", }; - private static Map<String, String> readProperties(String propFile) { + static Map<String, String> readProperties(String propFile) { // Use an ordered map just for cleaner dump log. final Map<String, String> ret = new LinkedHashMap<>(); try { @@ -60,7 +60,7 @@ public class RavenwoodSystemProperties { .map(String::trim) .filter(s -> !s.startsWith("#")) .map(s -> s.split("\\s*=\\s*", 2)) - .filter(a -> a.length == 2) + .filter(a -> a.length == 2 && a[1].length() > 0) .forEach(a -> ret.put(a[0], a[1])); } catch (IOException e) { throw new RuntimeException(e); diff --git a/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java b/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java index 520f050f0655..2a04d4469ef4 100644 --- a/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java +++ b/ravenwood/runtime-common-src/com/android/ravenwood/common/RavenwoodCommonUtils.java @@ -30,6 +30,7 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; +import java.util.function.Supplier; public class RavenwoodCommonUtils { private static final String TAG = "RavenwoodCommonUtils"; @@ -277,11 +278,55 @@ public class RavenwoodCommonUtils { (isStatic ? "static" : ""))); } + /** + * Run a supplier and swallow the exception, if any. + * + * It's a dangerous function. Only use it in an exception handler where we don't want to crash. + */ + @Nullable + public static <T> T runIgnoringException(@NonNull Supplier<T> s) { + try { + return s.get(); + } catch (Throwable th) { + log(TAG, "Warning: Exception detected! " + getStackTraceString(th)); + } + return null; + } + + /** + * Run a runnable and swallow the exception, if any. + * + * It's a dangerous function. Only use it in an exception handler where we don't want to crash. + */ + public static void runIgnoringException(@NonNull Runnable r) { + runIgnoringException(() -> { + r.run(); + return null; + }); + } + @NonNull - public static String getStackTraceString(@Nullable Throwable th) { + public static String getStackTraceString(@NonNull Throwable th) { StringWriter stringWriter = new StringWriter(); PrintWriter writer = new PrintWriter(stringWriter); th.printStackTrace(writer); return stringWriter.toString(); } + + /** Same as {@link Integer#parseInt(String)} but accepts null and returns null. */ + @Nullable + public static Integer parseNullableInt(@Nullable String value) { + if (value == null) { + return null; + } + return Integer.parseInt(value); + } + + /** + * @return {@code value} if it's non-null. Otherwise, returns {@code def}. + */ + @Nullable + public static <T> T withDefault(@Nullable T value, @Nullable T def) { + return value != null ? value : def; + } } diff --git a/ravenwood/scripts/run-ravenwood-tests.sh b/ravenwood/scripts/run-ravenwood-tests.sh index fe2269a8dc38..27c5ea1bd0d7 100755 --- a/ravenwood/scripts/run-ravenwood-tests.sh +++ b/ravenwood/scripts/run-ravenwood-tests.sh @@ -33,7 +33,7 @@ include_re="" exclude_re="" smoke_exclude_re="" dry_run="" -while getopts "sx:f:dt" opt; do +while getopts "sx:f:dtb" opt; do case "$opt" in s) # Remove slow tests. @@ -52,8 +52,13 @@ case "$opt" in dry_run="echo" ;; t) + # Redirect log to terminal export RAVENWOOD_LOG_OUT=$(tty) ;; + b) + # Build only + ATEST=m + ;; '?') exit 1 ;; @@ -99,11 +104,16 @@ done # Calculate the removed tests. -diff="$(diff <(echo "${all_tests[@]}" | tr ' ' '\n') <(echo "${targets[@]}" | tr ' ' '\n') )" +diff="$(diff <(echo "${all_tests[@]}" | tr ' ' '\n') <(echo "${targets[@]}" | tr ' ' '\n') | grep -v [0-9] )" if [[ "$diff" != "" ]]; then echo "Excluded tests:" echo "$diff" fi -$dry_run ${ATEST:-atest} "${targets[@]}" +run() { + echo "Running: ${@}" + "${@}" +} + +run $dry_run ${ATEST:-atest} "${targets[@]}" diff --git a/ravenwood/tests/bivalentinst/Android.bp b/ravenwood/tests/bivalentinst/Android.bp index 41e45e5a6d95..31e3bcc3634f 100644 --- a/ravenwood/tests/bivalentinst/Android.bp +++ b/ravenwood/tests/bivalentinst/Android.bp @@ -27,6 +27,9 @@ android_ravenwood_test { "junit", "truth", ], + + package_name: "com.android.ravenwood.bivalentinsttest_self_inst", + resource_apk: "RavenwoodBivalentInstTest_self_inst_device", auto_gen_config: true, } @@ -53,6 +56,10 @@ android_ravenwood_test { "truth", ], resource_apk: "RavenwoodBivalentInstTestTarget", + + package_name: "com.android.ravenwood.bivalentinst_target_app", + inst_package_name: "com.android.ravenwood.bivalentinsttest_nonself_inst", + inst_resource_apk: "RavenwoodBivalentInstTest_nonself_inst_device", auto_gen_config: true, } diff --git a/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_nonself.java b/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_nonself.java index ed1992cdd1ea..919aa439d4ef 100644 --- a/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_nonself.java +++ b/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_nonself.java @@ -19,9 +19,6 @@ import static com.google.common.truth.Truth.assertThat; import android.app.Instrumentation; import android.content.Context; -import android.platform.test.annotations.DisabledOnRavenwood; -import android.platform.test.ravenwood.RavenwoodConfig; -import android.platform.test.ravenwood.RavenwoodConfig.Config; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; @@ -34,18 +31,13 @@ import org.junit.runner.RunWith; * Tests for the case where the instrumentation target is _not_ the test APK itself. */ @RunWith(AndroidJUnit4.class) -@DisabledOnRavenwood(reason="AOSP is missing resources support") +@android.platform.test.annotations.DisabledOnRavenwood(reason = "AOSP is missing resources support") public class RavenwoodInstrumentationTest_nonself { private static final String TARGET_PACKAGE_NAME = "com.android.ravenwood.bivalentinst_target_app"; private static final String TEST_PACKAGE_NAME = "com.android.ravenwood.bivalentinsttest_nonself_inst"; - @Config - public static final RavenwoodConfig sConfig = new RavenwoodConfig.Builder() - .setPackageName(TEST_PACKAGE_NAME) - .setTargetPackageName(TARGET_PACKAGE_NAME) - .build(); private static Instrumentation sInstrumentation; private static Context sTestContext; diff --git a/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_self.java b/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_self.java index b5bafc435845..81cfa662920c 100644 --- a/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_self.java +++ b/ravenwood/tests/bivalentinst/test/com/android/ravenwoodtest/bivalentinst/RavenwoodInstrumentationTest_self.java @@ -19,9 +19,6 @@ import static com.google.common.truth.Truth.assertThat; import android.app.Instrumentation; import android.content.Context; -import android.platform.test.annotations.DisabledOnRavenwood; -import android.platform.test.ravenwood.RavenwoodConfig; -import android.platform.test.ravenwood.RavenwoodConfig.Config; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; @@ -34,7 +31,7 @@ import org.junit.runner.RunWith; * Tests for the case where the instrumentation target is the test APK itself. */ @RunWith(AndroidJUnit4.class) -@DisabledOnRavenwood(reason="AOSP is missing resources support") +@android.platform.test.annotations.DisabledOnRavenwood(reason = "AOSP is missing resources support") public class RavenwoodInstrumentationTest_self { private static final String TARGET_PACKAGE_NAME = @@ -42,13 +39,6 @@ public class RavenwoodInstrumentationTest_self { private static final String TEST_PACKAGE_NAME = "com.android.ravenwood.bivalentinsttest_self_inst"; - @Config - public static final RavenwoodConfig sConfig = new RavenwoodConfig.Builder() - .setPackageName(TEST_PACKAGE_NAME) - .setTargetPackageName(TARGET_PACKAGE_NAME) - .build(); - - private static Instrumentation sInstrumentation; private static Context sTestContext; private static Context sTargetContext; diff --git a/ravenwood/tests/bivalenttest/Android.bp b/ravenwood/tests/bivalenttest/Android.bp index 4895a1a6d1a2..ac545dfb06cc 100644 --- a/ravenwood/tests/bivalenttest/Android.bp +++ b/ravenwood/tests/bivalenttest/Android.bp @@ -58,6 +58,9 @@ java_defaults { java_defaults { name: "ravenwood-bivalent-device-defaults", defaults: ["ravenwood-bivalent-defaults"], + + target_sdk_version: "34", // For compat-framework tests + // TODO(b/371215487): migrate bivalenttest.ravenizer tests to another architecture exclude_srcs: [ "test/**/ravenizer/*.java", @@ -81,6 +84,8 @@ java_defaults { android_ravenwood_test { name: "RavenwoodBivalentTest", defaults: ["ravenwood-bivalent-defaults"], + target_sdk_version: "34", + package_name: "com.android.ravenwoodtest.bivalenttest", auto_gen_config: true, } diff --git a/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java index a5a16c14600b..306c2b39c70d 100644 --- a/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/RavenwoodConfigTest.java @@ -20,8 +20,6 @@ import static android.platform.test.ravenwood.RavenwoodConfig.isOnRavenwood; import static org.junit.Assert.assertEquals; import static org.junit.Assume.assumeTrue; -import android.platform.test.ravenwood.RavenwoodConfig; - import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; @@ -33,13 +31,7 @@ import org.junit.runner.RunWith; */ @RunWith(AndroidJUnit4.class) public class RavenwoodConfigTest { - private static final String PACKAGE_NAME = "com.test"; - - @RavenwoodConfig.Config - public static RavenwoodConfig sConfig = - new RavenwoodConfig.Builder() - .setPackageName(PACKAGE_NAME) - .build(); + private static final String PACKAGE_NAME = "com.android.ravenwoodtest.bivalenttest"; @Test public void testConfig() { diff --git a/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/compat/RavenwoodCompatFrameworkTest.kt b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/compat/RavenwoodCompatFrameworkTest.kt new file mode 100644 index 000000000000..882c91c43ee9 --- /dev/null +++ b/ravenwood/tests/bivalenttest/test/com/android/ravenwoodtest/bivalenttest/compat/RavenwoodCompatFrameworkTest.kt @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.ravenwoodtest.bivalenttest.compat + +import android.app.compat.CompatChanges +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.internal.ravenwood.RavenwoodEnvironment.CompatIdsForTest +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class RavenwoodCompatFrameworkTest { + @Test + fun testEnabled() { + Assert.assertTrue(CompatChanges.isChangeEnabled(CompatIdsForTest.TEST_COMPAT_ID_1)) + } + + @Test + fun testDisabled() { + Assert.assertFalse(CompatChanges.isChangeEnabled(CompatIdsForTest.TEST_COMPAT_ID_2)) + } + + @Test + fun testEnabledAfterSForUApps() { + Assert.assertTrue(CompatChanges.isChangeEnabled(CompatIdsForTest.TEST_COMPAT_ID_3)) + } + + @Test + fun testEnabledAfterUForUApps() { + Assert.assertFalse(CompatChanges.isChangeEnabled(CompatIdsForTest.TEST_COMPAT_ID_4)) + } +} diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java index 02d10732245d..f94b98bc1fb8 100644 --- a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java +++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerConfigValidationTest.java @@ -24,6 +24,7 @@ import android.platform.test.ravenwood.RavenwoodRule; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; @@ -32,6 +33,10 @@ import org.junit.runner.RunWith; /** * Test for @Config field extraction and validation. + * + * TODO(b/377765941) Most of the tests here will be obsolete and deleted with b/377765941, but + * some of the tests may need to be re-implemented one way or another. (e.g. the package name + * test.) Until that happens, we'll keep all tests here but add an {@code @Ignore} instead. */ @NoRavenizer // This class shouldn't be executed with RavenwoodAwareTestRunner. public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase { @@ -59,6 +64,7 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase testRunFinished: 1,0,0,0 """) // CHECKSTYLE:ON + @Ignore // Package name is no longer set via config. public static class ConfigInBaseClassTest extends ConfigInBaseClass { @Test public void test() { @@ -83,6 +89,7 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase testRunFinished: 1,0,0,0 """) // CHECKSTYLE:ON + @Ignore // Package name is no longer set via config. public static class ConfigOverridingTest extends ConfigInBaseClass { static String PACKAGE_NAME_OVERRIDE = "com.ConfigOverridingTest"; @@ -376,6 +383,7 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase testRunFinished: 1,0,0,0 """) // CHECKSTYLE:ON + @Ignore // Package name is no longer set via config. public static class RuleInBaseClassSuccessTest extends RuleInBaseClass { @Test @@ -437,6 +445,7 @@ public class RavenwoodRunnerConfigValidationTest extends RavenwoodRunnerTestBase testRunFinished: 1,1,0,0 """) // CHECKSTYLE:ON + @Ignore // Package name is no longer set via config. public static class RuleWithDifferentTypeInBaseClassSuccessTest extends RuleWithDifferentTypeInBaseClass { @Test diff --git a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerTestBase.java b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerTestBase.java index f7a2198a9bc4..0e3d053e90b1 100644 --- a/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerTestBase.java +++ b/ravenwood/tests/coretest/test/com/android/ravenwoodtest/runnercallbacktests/RavenwoodRunnerTestBase.java @@ -25,6 +25,8 @@ import android.util.Log; import junitparams.JUnitParamsRunner; import junitparams.Parameters; + +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.Description; import org.junit.runner.JUnitCore; @@ -103,6 +105,7 @@ public abstract class RavenwoodRunnerTestBase { var thisClass = this.getClass(); var ret = Arrays.stream(thisClass.getNestMembers()) .filter((c) -> c.getAnnotation(Expected.class) != null) + .filter((c) -> c.getAnnotation(Ignore.class) == null) .toArray(Class[]::new); assertThat(ret.length).isGreaterThan(0); diff --git a/ravenwood/tests/runtime-test/Android.bp b/ravenwood/tests/runtime-test/Android.bp index 0c0df1f993aa..c3520031ea7d 100644 --- a/ravenwood/tests/runtime-test/Android.bp +++ b/ravenwood/tests/runtime-test/Android.bp @@ -9,7 +9,7 @@ package { android_ravenwood_test { name: "RavenwoodRuntimeTest", - + target_sdk_version: "34", libs: [ "ravenwood-helper-runtime", ], diff --git a/ravenwood/tests/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesTest.java b/ravenwood/tests/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesTest.java index 52bf92e25f19..eeb71100cd9d 100644 --- a/ravenwood/tests/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesTest.java +++ b/ravenwood/tests/services-test/test/com/android/ravenwoodtest/servicestest/RavenwoodServicesTest.java @@ -24,7 +24,6 @@ import static org.junit.Assert.fail; import android.content.Context; import android.hardware.SerialManager; import android.hardware.SerialManagerInternal; -import android.platform.test.annotations.DisabledOnRavenwood; import android.platform.test.ravenwood.RavenwoodConfig; import android.platform.test.ravenwood.RavenwoodConfig.Config; @@ -70,7 +69,8 @@ public class RavenwoodServicesTest { } @Test - @DisabledOnRavenwood(reason="AOSP is missing resources support") + @android.platform.test.annotations.DisabledOnRavenwood( + reason = "AOSP is missing resources support") public void testSimple() { // Verify that we can obtain a manager, and talk to the backend service, and that no // serial ports are configured by default diff --git a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt index 5d24c3aea728..39e0cf90698e 100644 --- a/ravenwood/texts/ravenwood-annotation-allowed-classes.txt +++ b/ravenwood/texts/ravenwood-annotation-allowed-classes.txt @@ -366,3 +366,9 @@ com.android.server.utils.TimingsTraceAndSlog android.os.IpcDataCache android.app.PropertyInvalidatedCache + +android.app.compat.* +com.android.server.compat.* +com.android.internal.compat.* +android.app.AppCompatCallbacks + diff --git a/ravenwood/texts/ravenwood-services-policies.txt b/ravenwood/texts/ravenwood-services-policies.txt index cc2fa602b3c3..530e5c8f5986 100644 --- a/ravenwood/texts/ravenwood-services-policies.txt +++ b/ravenwood/texts/ravenwood-services-policies.txt @@ -1 +1,12 @@ # Ravenwood "policy" file for services.core. + +# Auto-generated from XSD +class com.android.server.compat.config.Change keepclass +class com.android.server.compat.config.Config keepclass +class com.android.server.compat.config.XmlParser keepclass +class com.android.server.compat.overrides.ChangeOverrides keepclass +class com.android.server.compat.overrides.OverrideValue keepclass +class com.android.server.compat.overrides.Overrides keepclass +class com.android.server.compat.overrides.RawOverrideValue keepclass +class com.android.server.compat.overrides.XmlParser keepclass +class com.android.server.compat.overrides.XmlWriter keepclass
\ No newline at end of file diff --git a/ravenwood/tools/hoststubgen/test-tiny-framework/diff-and-update-golden.sh b/ravenwood/tools/hoststubgen/test-tiny-framework/diff-and-update-golden.sh index 3726ca972564..b389a67a8e4c 100755 --- a/ravenwood/tools/hoststubgen/test-tiny-framework/diff-and-update-golden.sh +++ b/ravenwood/tools/hoststubgen/test-tiny-framework/diff-and-update-golden.sh @@ -30,7 +30,7 @@ help() { EOF } -source "${0%/*}"/../../common.sh +source "${0%/*}"/../common.sh SCRIPT_NAME="${0##*/}" @@ -61,7 +61,6 @@ esac done shift $(($OPTIND - 1)) - # Build the dump files, which are the input of this test. run m dump-jar tiny-framework-dump-test diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index 0e81eb914697..c31a4fb3569d 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -95,6 +95,7 @@ import java.util.Map; import java.util.Random; import java.util.Set; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Supplier; /** @@ -126,7 +127,7 @@ public class BiometricService extends SystemService { IGateKeeperService mGateKeeper; // Get and cache the available biometric authenticators and their associated info. - final ArrayList<BiometricSensor> mSensors = new ArrayList<>(); + final CopyOnWriteArrayList<BiometricSensor> mSensors = new CopyOnWriteArrayList<>(); @VisibleForTesting BiometricStrengthController mBiometricStrengthController; @@ -150,13 +151,13 @@ public class BiometricService extends SystemService { @NonNull private final Set<Integer> mSensorsPendingInvalidation; public static InvalidationTracker start(@NonNull Context context, - @NonNull ArrayList<BiometricSensor> sensors, - int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback) { + @NonNull List<BiometricSensor> sensors, int userId, + int fromSensorId, @NonNull IInvalidationCallback clientCallback) { return new InvalidationTracker(context, sensors, userId, fromSensorId, clientCallback); } private InvalidationTracker(@NonNull Context context, - @NonNull ArrayList<BiometricSensor> sensors, int userId, + @NonNull List<BiometricSensor> sensors, int userId, int fromSensorId, @NonNull IInvalidationCallback clientCallback) { mClientCallback = clientCallback; mSensorsPendingInvalidation = new ArraySet<>(); @@ -692,7 +693,7 @@ public class BiometricService extends SystemService { @android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL) @Override - public synchronized void registerAuthenticator(int id, int modality, + public void registerAuthenticator(int id, int modality, @Authenticators.Types int strength, @NonNull IBiometricAuthenticator authenticator) { diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java index f085647c9676..645206a91c0a 100644 --- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java +++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java @@ -174,10 +174,6 @@ class PreAuthInfo { return BIOMETRIC_NO_HARDWARE; } - if (sensor.modality == TYPE_FACE && biometricCameraManager.isAnyCameraUnavailable()) { - return BIOMETRIC_HARDWARE_NOT_DETECTED; - } - final boolean wasStrongEnough = Utils.isAtLeastStrength(sensor.oemStrength, requestedStrength); final boolean isStrongEnough = @@ -189,6 +185,10 @@ class PreAuthInfo { return BIOMETRIC_INSUFFICIENT_STRENGTH; } + if (sensor.modality == TYPE_FACE && biometricCameraManager.isAnyCameraUnavailable()) { + return BIOMETRIC_HARDWARE_NOT_DETECTED; + } + try { if (!sensor.impl.isHardwareDetected(opPackageName)) { return BIOMETRIC_HARDWARE_NOT_DETECTED; diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java index 82d5d4d8141d..e8786be4d8e6 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java @@ -677,10 +677,11 @@ public class BiometricScheduler<T, U> { * Start the timeout for the watchdog. */ public void startWatchdog() { - if (mCurrentOperation == null) { + final BiometricSchedulerOperation operation = mCurrentOperation; + if (operation == null) { + Slog.e(TAG, "Current operation is null,no need to start watchdog"); return; } - final BiometricSchedulerOperation operation = mCurrentOperation; mHandler.postDelayed(() -> { if (operation == mCurrentOperation && !operation.isFinished()) { Counter.logIncrement("biometric.value_scheduler_watchdog_triggered_count"); diff --git a/services/core/java/com/android/server/compat/CompatChange.java b/services/core/java/com/android/server/compat/CompatChange.java index a40dd7919402..c3d88e3e6eb1 100644 --- a/services/core/java/com/android/server/compat/CompatChange.java +++ b/services/core/java/com/android/server/compat/CompatChange.java @@ -50,6 +50,7 @@ import java.util.concurrent.ConcurrentHashMap; * * <p>Note, this class is not thread safe so callers must ensure thread safety. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class CompatChange extends CompatibilityChangeInfo { /** diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java index 79025d00d128..e89f43bd7196 100644 --- a/services/core/java/com/android/server/compat/CompatConfig.java +++ b/services/core/java/com/android/server/compat/CompatConfig.java @@ -42,6 +42,7 @@ import com.android.internal.compat.CompatibilityOverridesToRemoveByPackageConfig import com.android.internal.compat.CompatibilityOverridesToRemoveConfig; import com.android.internal.compat.IOverrideValidator; import com.android.internal.compat.OverrideAllowedState; +import com.android.internal.ravenwood.RavenwoodEnvironment; import com.android.server.compat.config.Change; import com.android.server.compat.config.Config; import com.android.server.compat.overrides.ChangeOverrides; @@ -63,6 +64,7 @@ import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Predicate; import javax.xml.datatype.DatatypeConfigurationException; @@ -72,12 +74,16 @@ import javax.xml.datatype.DatatypeConfigurationException; * <p>It stores the default configuration for each change, and any per-package overrides that have * been configured. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass final class CompatConfig { private static final String TAG = "CompatConfig"; private static final String APP_COMPAT_DATA_DIR = "/data/misc/appcompat"; private static final String STATIC_OVERRIDES_PRODUCT_DIR = "/product/etc/appcompat"; private static final String OVERRIDES_FILE = "compat_framework_overrides.xml"; + private static final String APP_COMPAT_DATA_DIR_RAVENWOOD = "/ravenwood-data/"; + private static final String OVERRIDES_FILE_RAVENWOOD = "compat-config.xml"; + private final ConcurrentHashMap<Long, CompatChange> mChanges = new ConcurrentHashMap<>(); private final OverrideValidatorImpl mOverrideValidator; @@ -98,19 +104,32 @@ final class CompatConfig { static CompatConfig create(AndroidBuildClassifier androidBuildClassifier, Context context) { CompatConfig config = new CompatConfig(androidBuildClassifier, context); - config.initConfigFromLib(Environment.buildPath( + config.loadConfigFiles(); + config.initOverrides(); + config.invalidateCache(); + return config; + } + + @android.ravenwood.annotation.RavenwoodReplace + private void loadConfigFiles() { + initConfigFromLib(Environment.buildPath( Environment.getRootDirectory(), "etc", "compatconfig")); - config.initConfigFromLib(Environment.buildPath( + initConfigFromLib(Environment.buildPath( Environment.getRootDirectory(), "system_ext", "etc", "compatconfig")); List<ApexManager.ActiveApexInfo> apexes = ApexManager.getInstance().getActiveApexInfos(); for (ApexManager.ActiveApexInfo apex : apexes) { - config.initConfigFromLib(Environment.buildPath( + initConfigFromLib(Environment.buildPath( apex.apexDirectory, "etc", "compatconfig")); } - config.initOverrides(); - config.invalidateCache(); - return config; + } + + @SuppressWarnings("unused") + private void loadConfigFiles$ravenwood() { + final var configDir = new File( + RavenwoodEnvironment.getInstance().getRavenwoodRuntimePath() + + APP_COMPAT_DATA_DIR_RAVENWOOD); + initConfigFromLib(configDir, (file) -> file.getName().endsWith(OVERRIDES_FILE_RAVENWOOD)); } /** @@ -678,12 +697,25 @@ final class CompatConfig { return changeInfos; } + /** + * Load all config files in a given directory. + */ void initConfigFromLib(File libraryDir) { + initConfigFromLib(libraryDir, (file) -> true); + } + + /** + * Load config files in a given directory, but only the ones that match {@code includingFilter}. + */ + void initConfigFromLib(File libraryDir, Predicate<File> includingFilter) { if (!libraryDir.exists() || !libraryDir.isDirectory()) { Slog.d(TAG, "No directory " + libraryDir + ", skipping"); return; } for (File f : libraryDir.listFiles()) { + if (!includingFilter.test(f)) { + continue; + } Slog.d(TAG, "Found a config file: " + f.getPath()); //TODO(b/138222363): Handle duplicate ids across config files. readConfig(f); diff --git a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java index e3b6d032b7f0..362c69797161 100644 --- a/services/core/java/com/android/server/compat/OverrideValidatorImpl.java +++ b/services/core/java/com/android/server/compat/OverrideValidatorImpl.java @@ -45,6 +45,7 @@ import com.android.internal.compat.OverrideAllowedState; /** * Implementation of the policy for allowing compat change overrides. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public class OverrideValidatorImpl extends IOverrideValidator.Stub { private AndroidBuildClassifier mAndroidBuildClassifier; diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java index df49affa4d6f..2186e2a397c5 100644 --- a/services/core/java/com/android/server/compat/PlatformCompat.java +++ b/services/core/java/com/android/server/compat/PlatformCompat.java @@ -36,6 +36,7 @@ import android.content.pm.PackageManagerInternal; import android.net.Uri; import android.os.Binder; import android.os.Build; +import android.os.PermissionEnforcer; import android.os.Process; import android.os.RemoteException; import android.os.UserHandle; @@ -65,6 +66,7 @@ import java.util.Map; /** * System server internal API for gating and reporting compatibility changes. */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public class PlatformCompat extends IPlatformCompat.Stub { private static final String TAG = "Compatibility"; @@ -75,6 +77,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { private final AndroidBuildClassifier mBuildClassifier; public PlatformCompat(Context context) { + super(PermissionEnforcer.fromContext(context)); mContext = context; mChangeReporter = new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER); mBuildClassifier = new AndroidBuildClassifier(); @@ -84,6 +87,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { @VisibleForTesting PlatformCompat(Context context, CompatConfig compatConfig, AndroidBuildClassifier buildClassifier) { + super(PermissionEnforcer.fromContext(context)); mContext = context; mChangeReporter = new ChangeReporter(ChangeReporter.SOURCE_SYSTEM_SERVER); mCompatConfig = compatConfig; @@ -492,6 +496,7 @@ public class PlatformCompat extends IPlatformCompat.Stub { packageName, 0, Process.myUid(), userId); } + @android.ravenwood.annotation.RavenwoodReplace private void killPackage(String packageName) { int uid = LocalServices.getService(PackageManagerInternal.class).getPackageUid(packageName, 0, UserHandle.myUserId()); @@ -505,6 +510,13 @@ public class PlatformCompat extends IPlatformCompat.Stub { killUid(UserHandle.getAppId(uid)); } + @SuppressWarnings("unused") + private void killPackage$ravenwood(String packageName) { + // TODO Maybe crash if the package is the self. + Slog.w(TAG, "killPackage() is ignored on Ravenwood: packageName=" + packageName); + } + + @android.ravenwood.annotation.RavenwoodReplace private void killUid(int appId) { final long identity = Binder.clearCallingIdentity(); try { @@ -519,6 +531,12 @@ public class PlatformCompat extends IPlatformCompat.Stub { } } + @SuppressWarnings("unused") + private void killUid$ravenwood(int appId) { + // TODO Maybe crash if the UID is the self. + Slog.w(TAG, "killUid() is ignored on Ravenwood: appId=" + appId); + } + private void checkAllCompatOverridesAreOverridable(Collection<Long> changeIds) { for (Long changeId : changeIds) { if (isKnownChangeId(changeId) && !mCompatConfig.isOverridable(changeId)) { diff --git a/services/core/java/com/android/server/compat/PlatformCompatNative.java b/services/core/java/com/android/server/compat/PlatformCompatNative.java index 5d7af650db0b..7a3feb515706 100644 --- a/services/core/java/com/android/server/compat/PlatformCompatNative.java +++ b/services/core/java/com/android/server/compat/PlatformCompatNative.java @@ -23,6 +23,7 @@ import com.android.internal.compat.IPlatformCompatNative; /** * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public class PlatformCompatNative extends IPlatformCompatNative.Stub { private final PlatformCompat mPlatformCompat; diff --git a/services/core/java/com/android/server/compat/overrides/AppCompatOverridesParser.java b/services/core/java/com/android/server/compat/overrides/AppCompatOverridesParser.java index e8762a3e935c..0ec68792a886 100644 --- a/services/core/java/com/android/server/compat/overrides/AppCompatOverridesParser.java +++ b/services/core/java/com/android/server/compat/overrides/AppCompatOverridesParser.java @@ -46,6 +46,7 @@ import java.util.regex.Pattern; * * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass final class AppCompatOverridesParser { /** * Flag for specifying all compat change IDs owned by a namespace. See {@link diff --git a/services/core/java/com/android/server/compat/overrides/AppCompatOverridesService.java b/services/core/java/com/android/server/compat/overrides/AppCompatOverridesService.java index fe002ce00d32..8637d2dfe565 100644 --- a/services/core/java/com/android/server/compat/overrides/AppCompatOverridesService.java +++ b/services/core/java/com/android/server/compat/overrides/AppCompatOverridesService.java @@ -68,6 +68,7 @@ import java.util.Set; * * @hide */ +@android.ravenwood.annotation.RavenwoodKeepWholeClass public final class AppCompatOverridesService { private static final String TAG = "AppCompatOverridesService"; diff --git a/services/core/java/com/android/server/display/OWNERS b/services/core/java/com/android/server/display/OWNERS index 9439eaa3a4c6..9f0cabfd9208 100644 --- a/services/core/java/com/android/server/display/OWNERS +++ b/services/core/java/com/android/server/display/OWNERS @@ -1,5 +1,4 @@ michaelwr@google.com -dangittik@google.com hackbod@google.com ogunwale@google.com santoscordon@google.com @@ -7,5 +6,6 @@ flc@google.com wilczynskip@google.com brup@google.com petsjonkin@google.com +olb@google.com per-file ColorDisplayService.java=christyfranks@google.com diff --git a/services/core/java/com/android/server/display/color/TintController.java b/services/core/java/com/android/server/display/color/TintController.java index 716661dd6c3c..68dc80fa51c8 100644 --- a/services/core/java/com/android/server/display/color/TintController.java +++ b/services/core/java/com/android/server/display/color/TintController.java @@ -19,6 +19,7 @@ package com.android.server.display.color; import android.animation.ValueAnimator; import android.content.Context; import android.util.Slog; +import com.android.internal.annotations.GuardedBy; import java.io.PrintWriter; @@ -29,23 +30,33 @@ abstract class TintController { */ private static final long TRANSITION_DURATION = 3000L; + private final Object mLock = new Object(); + + @GuardedBy("mLock") private ValueAnimator mAnimator; + @GuardedBy("mLock") private Boolean mIsActivated; public ValueAnimator getAnimator() { - return mAnimator; + synchronized (mLock) { + return mAnimator; + } } public void setAnimator(ValueAnimator animator) { - mAnimator = animator; + synchronized (mLock) { + mAnimator = animator; + } } /** * Cancel the animator if it's still running. */ public void cancelAnimator() { - if (mAnimator != null) { - mAnimator.cancel(); + synchronized (mLock) { + if (mAnimator != null) { + mAnimator.cancel(); + } } } @@ -53,22 +64,30 @@ abstract class TintController { * End the animator if it's still running, jumping to the end state. */ public void endAnimator() { - if (mAnimator != null) { - mAnimator.end(); - mAnimator = null; + synchronized (mLock) { + if (mAnimator != null) { + mAnimator.end(); + mAnimator = null; + } } } public void setActivated(Boolean isActivated) { - mIsActivated = isActivated; + synchronized (mLock) { + mIsActivated = isActivated; + } } public boolean isActivated() { - return mIsActivated != null && mIsActivated; + synchronized (mLock) { + return mIsActivated != null && mIsActivated; + } } public boolean isActivatedStateNotSet() { - return mIsActivated == null; + synchronized (mLock) { + return mIsActivated == null; + } } public long getTransitionDurationMilliseconds() { diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java index bb4ae96da53b..a132876b72a3 100644 --- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java +++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java @@ -46,7 +46,6 @@ import android.util.Slog; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; -import com.android.server.integrity.model.RuleMetadata; import java.io.File; import java.nio.charset.StandardCharsets; diff --git a/services/core/java/com/android/server/integrity/model/BitInputStream.java b/services/core/java/com/android/server/integrity/model/BitInputStream.java deleted file mode 100644 index e7cc81eab26b..000000000000 --- a/services/core/java/com/android/server/integrity/model/BitInputStream.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.integrity.model; - -import java.io.IOException; -import java.io.InputStream; - -/** A wrapper class for reading a stream of bits. - * - * <p>Note: this class reads from underlying stream byte-by-byte. It is advised to apply buffering - * to underlying streams. - */ -public class BitInputStream { - - private long mBitsRead; - - private InputStream mInputStream; - - private byte mCurrentByte; - - public BitInputStream(InputStream inputStream) { - mInputStream = inputStream; - } - - /** - * Read the next number of bits from the stream. - * - * @param numOfBits The number of bits to read. - * @return The value read from the stream. - */ - public int getNext(int numOfBits) throws IOException { - int component = 0; - int count = 0; - - while (count++ < numOfBits) { - if (mBitsRead % 8 == 0) { - mCurrentByte = getNextByte(); - } - int offset = 7 - (int) (mBitsRead % 8); - - component <<= 1; - component |= (mCurrentByte >>> offset) & 1; - - mBitsRead++; - } - - return component; - } - - /** Check if there are bits left in the stream. */ - public boolean hasNext() throws IOException { - return mInputStream.available() > 0; - } - - private byte getNextByte() throws IOException { - return (byte) mInputStream.read(); - } -} diff --git a/services/core/java/com/android/server/integrity/model/BitOutputStream.java b/services/core/java/com/android/server/integrity/model/BitOutputStream.java deleted file mode 100644 index 14b35fd016eb..000000000000 --- a/services/core/java/com/android/server/integrity/model/BitOutputStream.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.integrity.model; - -import static com.android.server.integrity.model.ComponentBitSize.BYTE_BITS; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.Arrays; - -/** A wrapper class for writing a stream of bits. */ -public class BitOutputStream { - - private static final int BUFFER_SIZE = 4 * 1024; - - private int mNextBitIndex; - - private final OutputStream mOutputStream; - private final byte[] mBuffer; - - public BitOutputStream(OutputStream outputStream) { - mBuffer = new byte[BUFFER_SIZE]; - mNextBitIndex = 0; - mOutputStream = outputStream; - } - - /** - * Set the next number of bits in the stream to value. - * - * @param numOfBits The number of bits used to represent the value. - * @param value The value to convert to bits. - */ - public void setNext(int numOfBits, int value) throws IOException { - if (numOfBits <= 0) { - return; - } - - // optional: we can do some clever size checking to "OR" an entire segment of bits instead - // of setting bits one by one, but it is probably not worth it. - int nextBitMask = 1 << (numOfBits - 1); - while (numOfBits-- > 0) { - setNext((value & nextBitMask) != 0); - nextBitMask >>>= 1; - } - } - - /** - * Set the next bit in the stream to value. - * - * @param value The value to set the bit to - */ - public void setNext(boolean value) throws IOException { - int byteToWrite = mNextBitIndex / BYTE_BITS; - if (byteToWrite == BUFFER_SIZE) { - mOutputStream.write(mBuffer); - reset(); - byteToWrite = 0; - } - if (value) { - mBuffer[byteToWrite] |= 1 << (BYTE_BITS - 1 - (mNextBitIndex % BYTE_BITS)); - } - mNextBitIndex++; - } - - /** Set the next bit in the stream to true. */ - public void setNext() throws IOException { - setNext(/* value= */ true); - } - - /** - * Flush the data written to the underlying {@link java.io.OutputStream}. Any unfinished bytes - * will be padded with 0. - */ - public void flush() throws IOException { - int endByte = mNextBitIndex / BYTE_BITS; - if (mNextBitIndex % BYTE_BITS != 0) { - // If next bit is not the first bit of a byte, then mNextBitIndex / BYTE_BITS would be - // the byte that includes already written bits. We need to increment it so this byte - // gets written. - endByte++; - } - mOutputStream.write(mBuffer, 0, endByte); - reset(); - } - - /** Reset this output stream to start state. */ - private void reset() { - mNextBitIndex = 0; - Arrays.fill(mBuffer, (byte) 0); - } -} diff --git a/services/core/java/com/android/server/integrity/model/ByteTrackedOutputStream.java b/services/core/java/com/android/server/integrity/model/ByteTrackedOutputStream.java deleted file mode 100644 index ceed054e4a53..000000000000 --- a/services/core/java/com/android/server/integrity/model/ByteTrackedOutputStream.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.integrity.model; - -import java.io.IOException; -import java.io.OutputStream; - -/** - * An output stream that tracks the total number written bytes since construction and allows - * querying this value any time during the execution. - * - * <p>This class is used for constructing the rule indexing. - */ -public class ByteTrackedOutputStream extends OutputStream { - - private int mWrittenBytesCount; - private final OutputStream mOutputStream; - - public ByteTrackedOutputStream(OutputStream outputStream) { - mWrittenBytesCount = 0; - mOutputStream = outputStream; - } - - @Override - public void write(int b) throws IOException { - mWrittenBytesCount++; - mOutputStream.write(b); - } - - /** - * Writes the given bytes into the output stream provided in constructor and updates the total - * number of written bytes. - */ - @Override - public void write(byte[] bytes) throws IOException { - write(bytes, 0, bytes.length); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - mWrittenBytesCount += len; - mOutputStream.write(b, off, len); - } - - /** Returns the total number of bytes written into the output stream at the requested time. */ - public int getWrittenBytesCount() { - return mWrittenBytesCount; - } -} diff --git a/services/core/java/com/android/server/integrity/model/ComponentBitSize.java b/services/core/java/com/android/server/integrity/model/ComponentBitSize.java deleted file mode 100644 index 94e6708c3038..000000000000 --- a/services/core/java/com/android/server/integrity/model/ComponentBitSize.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.integrity.model; - -import android.content.integrity.Rule; - -/** - * A helper class containing information about the binary representation of different {@link Rule} - * components. - */ -public final class ComponentBitSize { - public static final int FORMAT_VERSION_BITS = 8; - - public static final int EFFECT_BITS = 3; - public static final int KEY_BITS = 4; - public static final int OPERATOR_BITS = 3; - public static final int CONNECTOR_BITS = 2; - public static final int SEPARATOR_BITS = 3; - public static final int VALUE_SIZE_BITS = 8; - public static final int IS_HASHED_BITS = 1; - - public static final int ATOMIC_FORMULA_START = 0; - public static final int COMPOUND_FORMULA_START = 1; - public static final int COMPOUND_FORMULA_END = 2; - public static final int INSTALLER_ALLOWED_BY_MANIFEST_START = 3; - - public static final int DEFAULT_FORMAT_VERSION = 1; - public static final int SIGNAL_BIT = 1; - - public static final int BYTE_BITS = 8; -} diff --git a/services/core/java/com/android/server/integrity/model/IndexingFileConstants.java b/services/core/java/com/android/server/integrity/model/IndexingFileConstants.java deleted file mode 100644 index 0c4052adc3ed..000000000000 --- a/services/core/java/com/android/server/integrity/model/IndexingFileConstants.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.integrity.model; - -/** A helper class containing special indexing file constants. */ -public final class IndexingFileConstants { - // We empirically experimented with different block sizes and identified that 50 is in the - // optimal range of efficient computation. - public static final int INDEXING_BLOCK_SIZE = 50; - - public static final String START_INDEXING_KEY = "START_KEY"; - public static final String END_INDEXING_KEY = "END_KEY"; -} diff --git a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java b/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java deleted file mode 100644 index b0647fc46473..000000000000 --- a/services/core/java/com/android/server/integrity/model/IntegrityCheckResult.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.integrity.model; - -import android.annotation.Nullable; -import android.content.integrity.Rule; - -import java.util.Collections; -import java.util.List; - -/** - * A class encapsulating the result from the evaluation engine after evaluating rules against app - * install metadata. - * - * <p>It contains the outcome effect (whether to allow or block the install), and the rule causing - * that effect. - */ -public final class IntegrityCheckResult { - - public enum Effect { - ALLOW, - DENY - } - - private final Effect mEffect; - private final List<Rule> mRuleList; - - private IntegrityCheckResult(Effect effect, @Nullable List<Rule> ruleList) { - this.mEffect = effect; - this.mRuleList = ruleList; - } - - public Effect getEffect() { - return mEffect; - } - - public List<Rule> getMatchedRules() { - return mRuleList; - } - - /** - * Create an ALLOW evaluation outcome. - * - * @return An evaluation outcome with ALLOW effect and no rule. - */ - public static IntegrityCheckResult allow() { - return new IntegrityCheckResult(Effect.ALLOW, Collections.emptyList()); - } - - /** - * Create an ALLOW evaluation outcome. - * - * @return An evaluation outcome with ALLOW effect and rule causing that effect. - */ - public static IntegrityCheckResult allow(List<Rule> ruleList) { - return new IntegrityCheckResult(Effect.ALLOW, ruleList); - } - - /** - * Create a DENY evaluation outcome. - * - * @param ruleList All valid rules that cause the DENY effect. - * @return An evaluation outcome with DENY effect and rule causing that effect. - */ - public static IntegrityCheckResult deny(List<Rule> ruleList) { - return new IntegrityCheckResult(Effect.DENY, ruleList); - } - - /** Returns true when the {@code mEffect} is caused by an app certificate mismatch. */ - public boolean isCausedByAppCertRule() { - return mRuleList.stream().anyMatch(rule -> rule.getFormula().isAppCertificateFormula()); - } - - /** Returns true when the {@code mEffect} is caused by an installer rule. */ - public boolean isCausedByInstallerRule() { - return mRuleList.stream().anyMatch(rule -> rule.getFormula().isInstallerFormula()); - } - -} diff --git a/services/core/java/com/android/server/integrity/model/RuleMetadata.java b/services/core/java/com/android/server/integrity/model/RuleMetadata.java deleted file mode 100644 index 6b582ae7b5f2..000000000000 --- a/services/core/java/com/android/server/integrity/model/RuleMetadata.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.integrity.model; - -import android.annotation.Nullable; - -/** Data class containing relevant metadata associated with a rule set. */ -public class RuleMetadata { - - private final String mRuleProvider; - private final String mVersion; - - public RuleMetadata(String ruleProvider, String version) { - mRuleProvider = ruleProvider; - mVersion = version; - } - - @Nullable - public String getRuleProvider() { - return mRuleProvider; - } - - @Nullable - public String getVersion() { - return mVersion; - } -} diff --git a/services/core/java/com/android/server/location/contexthub/OWNERS b/services/core/java/com/android/server/location/contexthub/OWNERS index c62e3237e487..6536ca084421 100644 --- a/services/core/java/com/android/server/location/contexthub/OWNERS +++ b/services/core/java/com/android/server/location/contexthub/OWNERS @@ -1,3 +1,4 @@ bduddie@google.com +arthuri@google.com matthewsedam@google.com stange@google.com diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java index ada812e58e77..d99fc3eda5d3 100644 --- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java +++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java @@ -235,6 +235,7 @@ final class DefaultPermissionGrantPolicy { NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_SCAN); NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.UWB_RANGING); NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.NEARBY_WIFI_DEVICES); + NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.RANGING); } private static final Set<String> NOTIFICATION_PERMISSIONS = new ArraySet<>(); diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 89ddb3fd3e88..a17de65bf7f5 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -824,7 +824,8 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub if (windowingMode > -1) { if (mService.isInLockTaskMode() - && WindowConfiguration.inMultiWindowMode(windowingMode)) { + && WindowConfiguration.inMultiWindowMode(windowingMode) + && !container.isEmbedded()) { Slog.w(TAG, "Dropping unsupported request to set multi-window windowing mode" + " during locked task mode."); return effects; diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index 52a2fd6e4955..688312e7e004 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -2968,7 +2968,10 @@ public final class SystemServer implements Dumpable { if (com.android.ranging.flags.Flags.rangingStackEnabled()) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_UWB) || context.getPackageManager().hasSystemFeature( - PackageManager.FEATURE_WIFI_RTT)) { + PackageManager.FEATURE_WIFI_RTT) + || (com.android.ranging.flags.Flags.rangingCsEnabled() + && context.getPackageManager().hasSystemFeature( + PackageManager.FEATURE_BLUETOOTH_LE_CHANNEL_SOUNDING))) { t.traceBegin("RangingService"); // TODO: b/375264320 - Remove after RELEASE_RANGING_STACK is ramped to next. try { diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index 4e868887ea1b..e307e529a40b 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -144,6 +144,10 @@ public final class ProfcollectForwardingService extends SystemService { public void onBootPhase(int phase) { if (phase == PHASE_SYSTEM_SERVICES_READY) { UsbManager usbManager = getContext().getSystemService(UsbManager.class); + if (usbManager == null) { + mAdbActive = false; + return; + } mAdbActive = ((usbManager.getCurrentFunctions() & UsbManager.FUNCTION_ADB) == 1); Log.d(LOG_TAG, "ADB is " + mAdbActive + " on system startup"); } diff --git a/services/tests/VpnTests/java/com/android/server/connectivity/VpnTest.java b/services/tests/VpnTests/java/com/android/server/connectivity/VpnTest.java index 08155c7b3f98..9772ef929eae 100644 --- a/services/tests/VpnTests/java/com/android/server/connectivity/VpnTest.java +++ b/services/tests/VpnTests/java/com/android/server/connectivity/VpnTest.java @@ -2380,10 +2380,14 @@ public class VpnTest extends VpnTestBase { @Test public void doTestMigrateIkeSession_Vcn() throws Exception { final int expectedKeepalive = 2097; // Any unlikely number will do - final NetworkCapabilities vcnNc = new NetworkCapabilities.Builder() - .addTransportType(TRANSPORT_CELLULAR) - .setTransportInfo(new VcnTransportInfo(TEST_SUB_ID, expectedKeepalive)) - .build(); + final NetworkCapabilities vcnNc = + new NetworkCapabilities.Builder() + .addTransportType(TRANSPORT_CELLULAR) + .setTransportInfo( + new VcnTransportInfo.Builder() + .setMinUdpPort4500NatTimeoutSeconds(expectedKeepalive) + .build()) + .build(); final Ikev2VpnProfile ikev2VpnProfile = makeIkeV2VpnProfile( true /* isAutomaticIpVersionSelectionEnabled */, true /* isAutomaticNattKeepaliveTimerEnabled */, diff --git a/services/tests/apexsystemservices/services/Android.bp b/services/tests/apexsystemservices/services/Android.bp index 477ea4cdad37..70d84dcf6007 100644 --- a/services/tests/apexsystemservices/services/Android.bp +++ b/services/tests/apexsystemservices/services/Android.bp @@ -17,4 +17,5 @@ java_library { ], visibility: ["//frameworks/base/services/tests/apexsystemservices:__subpackages__"], apex_available: ["//apex_available:anyapex"], + compile_dex: true, } diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index d336c9962c17..c09886807884 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -149,21 +149,49 @@ android_test { resource_zips: [":FrameworksServicesTests_apks_as_resources"], } -android_ravenwood_test { - name: "FrameworksServicesTestsRavenwood", +java_defaults { + name: "FrameworksServicesTestsRavenwood-defaults", libs: [ "android.test.mock.stubs.system", ], static_libs: [ "androidx.annotation_annotation", "androidx.test.rules", - "services.core", "flag-junit", ], + auto_gen_config: true, +} + +// Unit tests for UriGrantManager, running on ravenwood. +// Note UriGrantManager does not support Ravenwood (yet). We're just running the original +// unit tests as is on Ravenwood. So here, we use the original "services.core", because +// "services.core.ravenwood" doesn't have the target code. +// (Compare to FrameworksServicesTestsRavenwood_Compat, which does support Ravenwood.) +android_ravenwood_test { + name: "FrameworksServicesTestsRavenwood_Uri", + defaults: ["FrameworksServicesTestsRavenwood-defaults"], + team: "trendy_team_ravenwood", + static_libs: [ + "services.core", + ], srcs: [ "src/com/android/server/uri/**/*.java", ], - auto_gen_config: true, +} + +// Unit tests for compat-framework. +// Compat-framework does support Ravenwood, and it uses the ravenwood anottations, +// so we link "services.core.ravenwood". +android_ravenwood_test { + name: "FrameworksServicesTestsRavenwood_Compat", + defaults: ["FrameworksServicesTestsRavenwood-defaults"], + team: "trendy_team_ravenwood", + static_libs: [ + "services.core.ravenwood", + ], + srcs: [ + "src/com/android/server/compat/**/*.java", + ], } java_library { diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java index b40d7ee39a4c..67202174535c 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java @@ -20,6 +20,7 @@ import static android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NO import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.biometrics.BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; +import static android.hardware.biometrics.BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE; import static com.android.server.biometrics.sensors.LockoutTracker.LOCKOUT_NONE; @@ -55,6 +56,7 @@ public class PreAuthInfoTest { @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + private static final int USER_ID = 0; private static final int SENSOR_ID_FINGERPRINT = 0; private static final int SENSOR_ID_FACE = 1; private static final String TEST_PACKAGE_NAME = "PreAuthInfoTestPackage"; @@ -184,6 +186,20 @@ public class PreAuthInfoTest { assertThat(preAuthInfo.eligibleSensors.get(0).modality).isEqualTo(TYPE_FINGERPRINT); } + @Test + public void prioritizeStrengthErrorBeforeCameraUnavailableError() throws Exception { + final BiometricSensor sensor = getFaceSensorWithStrength( + BiometricManager.Authenticators.BIOMETRIC_WEAK); + final PromptInfo promptInfo = new PromptInfo(); + promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); + promptInfo.setNegativeButtonText(TEST_PACKAGE_NAME); + final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager, + mSettingObserver, List.of(sensor), USER_ID , promptInfo, TEST_PACKAGE_NAME, + false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager); + + assertThat(preAuthInfo.getCanAuthenticateResult()).isEqualTo(BIOMETRIC_ERROR_NO_HARDWARE); + } + private BiometricSensor getFingerprintSensor() { BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FINGERPRINT, TYPE_FINGERPRINT, BiometricManager.Authenticators.BIOMETRIC_STRONG, @@ -202,9 +218,10 @@ public class PreAuthInfoTest { return sensor; } - private BiometricSensor getFaceSensor() { + private BiometricSensor getFaceSensorWithStrength( + @BiometricManager.Authenticators.Types int sensorStrength) { BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FACE, TYPE_FACE, - BiometricManager.Authenticators.BIOMETRIC_STRONG, mFaceAuthenticator) { + sensorStrength, mFaceAuthenticator) { @Override boolean confirmationAlwaysRequired(int userId) { return false; @@ -218,4 +235,8 @@ public class PreAuthInfoTest { return sensor; } + + private BiometricSensor getFaceSensor() { + return getFaceSensorWithStrength(BiometricManager.Authenticators.BIOMETRIC_STRONG); + } } diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java index 36b163ec84b6..3d695a68f1f9 100644 --- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java @@ -18,12 +18,12 @@ package com.android.server.compat; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import static org.testng.Assert.assertThrows; import android.app.compat.ChangeIdStateCache; import android.app.compat.PackageOverride; diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java index 9accd49bc392..79f0673d91bd 100644 --- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java +++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java @@ -18,6 +18,7 @@ package com.android.server.compat; import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.never; @@ -25,13 +26,15 @@ import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import static org.mockito.internal.verification.VerificationModeFactory.times; -import static org.testng.Assert.assertThrows; import android.compat.Compatibility.ChangeConfig; +import android.content.AttributionSource; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.os.Build; +import android.os.PermissionEnforcer; +import android.permission.PermissionCheckerManager; import androidx.test.runner.AndroidJUnit4; @@ -77,6 +80,22 @@ public class PlatformCompatTest { .thenReturn(-1); when(mPackageManager.getApplicationInfo(eq(PACKAGE_NAME), anyInt())) .thenThrow(new PackageManager.NameNotFoundException()); + + var allGrantingPermissionEnforcer = new PermissionEnforcer() { + @Override + protected int checkPermission(String permission, AttributionSource source) { + return PermissionCheckerManager.PERMISSION_GRANTED; + } + + @Override + protected int checkPermission(String permission, int pid, int uid) { + return PermissionCheckerManager.PERMISSION_GRANTED; + } + }; + + when(mContext.getSystemService(eq(Context.PERMISSION_ENFORCER_SERVICE))) + .thenReturn(allGrantingPermissionEnforcer); + mCompatConfig = new CompatConfig(mBuildClassifier, mContext); mPlatformCompat = new PlatformCompat(mContext, mCompatConfig, mBuildClassifier); // Assume userdebug/eng non-final build diff --git a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java index 93aa10b9112f..fd221185bacf 100644 --- a/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java +++ b/services/tests/servicestests/src/com/android/server/integrity/AppIntegrityManagerServiceImplTest.java @@ -68,7 +68,6 @@ import androidx.test.InstrumentationRegistry; import com.android.internal.R; import com.android.server.compat.PlatformCompat; -import com.android.server.integrity.model.IntegrityCheckResult; import com.android.server.testutils.TestUtils; import org.junit.After; diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/ByteTrackedOutputStreamTest.java b/services/tests/servicestests/src/com/android/server/integrity/model/ByteTrackedOutputStreamTest.java deleted file mode 100644 index 57274bf13499..000000000000 --- a/services/tests/servicestests/src/com/android/server/integrity/model/ByteTrackedOutputStreamTest.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.integrity.model; - -import static com.google.common.truth.Truth.assertThat; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.io.ByteArrayOutputStream; - -@RunWith(JUnit4.class) -public class ByteTrackedOutputStreamTest { - - @Test - public void testConstructorStartsWithZeroBytesWritten() { - ByteTrackedOutputStream byteTrackedOutputStream = - new ByteTrackedOutputStream(new ByteArrayOutputStream()); - - assertThat(byteTrackedOutputStream.getWrittenBytesCount()).isEqualTo(0); - } - - @Test - public void testSuccessfulWriteAndValidateWrittenBytesCount_directFromByteArray() - throws Exception { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - ByteTrackedOutputStream byteTrackedOutputStream = new ByteTrackedOutputStream(outputStream); - - byte[] outputContent = "This is going to be outputed for tests.".getBytes(); - byteTrackedOutputStream.write(outputContent); - - assertThat(byteTrackedOutputStream.getWrittenBytesCount()).isEqualTo(outputContent.length); - assertThat(outputStream.toByteArray().length).isEqualTo(outputContent.length); - } - - @Test - public void testSuccessfulWriteAndValidateWrittenBytesCount_fromBitStream() throws Exception { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - ByteTrackedOutputStream byteTrackedOutputStream = new ByteTrackedOutputStream(outputStream); - - BitOutputStream bitOutputStream = new BitOutputStream(byteTrackedOutputStream); - bitOutputStream.setNext(/* numOfBits= */5, /* value= */1); - bitOutputStream.flush(); - - // Even though we wrote 5 bits, this will complete to 1 byte. - assertThat(byteTrackedOutputStream.getWrittenBytesCount()).isEqualTo(1); - - // Add a bit less than 2 bytes (10 bits). - bitOutputStream.setNext(/* numOfBits= */10, /* value= */1); - bitOutputStream.flush(); - assertThat(byteTrackedOutputStream.getWrittenBytesCount()).isEqualTo(3); - - assertThat(outputStream.toByteArray().length).isEqualTo(3); - } -} diff --git a/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java b/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java deleted file mode 100644 index d31ed689a7da..000000000000 --- a/services/tests/servicestests/src/com/android/server/integrity/model/IntegrityCheckResultTest.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.integrity.model; - -import static com.google.common.truth.Truth.assertThat; - -import android.content.integrity.AtomicFormula; -import android.content.integrity.CompoundFormula; -import android.content.integrity.Rule; - -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.JUnit4; - -import java.util.Arrays; -import java.util.Collections; - -@RunWith(JUnit4.class) -public class IntegrityCheckResultTest { - - @Test - public void createAllowResult() { - IntegrityCheckResult allowResult = IntegrityCheckResult.allow(); - - assertThat(allowResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.ALLOW); - assertThat(allowResult.getMatchedRules()).isEmpty(); - } - - @Test - public void createAllowResultWithRule() { - String packageName = "com.test.deny"; - Rule forceAllowRule = - new Rule( - new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, - packageName), - Rule.FORCE_ALLOW); - - IntegrityCheckResult allowResult = - IntegrityCheckResult.allow(Collections.singletonList(forceAllowRule)); - - assertThat(allowResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.ALLOW); - assertThat(allowResult.getMatchedRules()).containsExactly(forceAllowRule); - } - - @Test - public void createDenyResultWithRule() { - String packageName = "com.test.deny"; - Rule failedRule = - new Rule( - new AtomicFormula.StringAtomicFormula(AtomicFormula.PACKAGE_NAME, - packageName), - Rule.DENY); - - IntegrityCheckResult denyResult = - IntegrityCheckResult.deny(Collections.singletonList(failedRule)); - - assertThat(denyResult.getEffect()).isEqualTo(IntegrityCheckResult.Effect.DENY); - assertThat(denyResult.getMatchedRules()).containsExactly(failedRule); - } - - @Test - public void isDenyCausedByAppCertificate() { - String packageName = "com.test.deny"; - String appCert = "app-cert"; - Rule failedRule = - new Rule( - new CompoundFormula( - CompoundFormula.AND, - Arrays.asList( - new AtomicFormula.StringAtomicFormula( - AtomicFormula.PACKAGE_NAME, packageName), - new AtomicFormula.StringAtomicFormula( - AtomicFormula.APP_CERTIFICATE, appCert))), - Rule.DENY); - Rule otherFailedRule = - new Rule( - new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, - AtomicFormula.EQ, 12), - Rule.DENY); - - IntegrityCheckResult denyResult = - IntegrityCheckResult.deny(Arrays.asList(failedRule, otherFailedRule)); - - assertThat(denyResult.isCausedByAppCertRule()).isTrue(); - assertThat(denyResult.isCausedByInstallerRule()).isFalse(); - } - - @Test - public void isDenyCausedByInstaller() { - String packageName = "com.test.deny"; - String appCert = "app-cert"; - Rule failedRule = - new Rule( - new CompoundFormula( - CompoundFormula.AND, - Arrays.asList( - new AtomicFormula.StringAtomicFormula( - AtomicFormula.PACKAGE_NAME, packageName), - new AtomicFormula.StringAtomicFormula( - AtomicFormula.INSTALLER_CERTIFICATE, appCert))), - Rule.DENY); - Rule otherFailedRule = - new Rule( - new AtomicFormula.LongAtomicFormula(AtomicFormula.VERSION_CODE, - AtomicFormula.EQ, 12), - Rule.DENY); - - IntegrityCheckResult denyResult = - IntegrityCheckResult.deny(Arrays.asList(failedRule, otherFailedRule)); - - assertThat(denyResult.isCausedByAppCertRule()).isFalse(); - assertThat(denyResult.isCausedByInstallerRule()).isTrue(); - } -} diff --git a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java index 24abc183cad1..f5494534716a 100644 --- a/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/uri/UriGrantsManagerServiceTest.java @@ -61,7 +61,6 @@ import android.os.Process; import android.os.UserHandle; import android.platform.test.flag.junit.FlagsParameterization; import android.platform.test.flag.junit.SetFlagsRule; -import android.platform.test.ravenwood.RavenwoodRule; import android.util.ArraySet; import org.junit.Before; @@ -77,9 +76,6 @@ import java.util.Set; @RunWith(Parameterized.class) public class UriGrantsManagerServiceTest { - @Rule - public final RavenwoodRule mRavenwood = new RavenwoodRule(); - /** * Why this class needs to test all combinations of * {@link android.security.Flags#FLAG_CONTENT_URI_PERMISSION_APIS}: diff --git a/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java b/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java index 611c51463246..fe66f738487d 100644 --- a/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java +++ b/services/tests/servicestests/src/com/android/server/uri/UriPermissionTest.java @@ -37,18 +37,13 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; import android.os.SystemClock; -import android.platform.test.ravenwood.RavenwoodRule; import org.junit.Before; -import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; public class UriPermissionTest { - @Rule - public final RavenwoodRule mRavenwood = new RavenwoodRule(); - @Mock private UriGrantsManagerInternal mService; |