diff options
127 files changed, 6674 insertions, 1274 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java index dcc324deaac6..5c60562398ee 100644 --- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java +++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java @@ -75,7 +75,7 @@ class Agent { private static final String ALARM_TAG_AFFORDABILITY_CHECK = "*tare.affordability_check*"; private final Object mLock; - private final Handler mHandler; + private final AgentHandler mHandler; private final Analyst mAnalyst; private final InternalResourceService mIrs; private final Scribe mScribe; @@ -992,6 +992,7 @@ class Agent { void tearDownLocked() { mCurrentOngoingEvents.clear(); mBalanceThresholdAlarmQueue.removeAllAlarms(); + mHandler.removeAllMessages(); } @VisibleForTesting @@ -1290,6 +1291,11 @@ class Agent { break; } } + + void removeAllMessages() { + removeMessages(MSG_CHECK_ALL_AFFORDABILITY); + removeMessages(MSG_CHECK_INDIVIDUAL_AFFORDABILITY); + } } @GuardedBy("mLock") diff --git a/api/StubLibraries.bp b/api/StubLibraries.bp index e481fe9971fc..2f84df70fc40 100644 --- a/api/StubLibraries.bp +++ b/api/StubLibraries.bp @@ -33,7 +33,7 @@ droidstubs { "android-non-updatable-stubs-defaults", "module-classpath-stubs-defaults", ], - args: metalava_framework_docs_args, + args: metalava_framework_docs_args + "--error UnflaggedApi ", check_api: { current: { api_file: ":non-updatable-current.txt", @@ -47,6 +47,7 @@ droidstubs { api_lint: { enabled: true, new_since: ":android.api.public.latest", + baseline_file: ":non-updatable-lint-baseline.txt", }, }, dists: [ @@ -73,7 +74,8 @@ priv_apps_in_stubs = " --show-for-stub-purposes-annotation android.annotation.Sy "client=android.annotation.SystemApi.Client.PRIVILEGED_APPS" + "\\)" -test = " --show-annotation android.annotation.TestApi" +test = " --show-annotation android.annotation.TestApi" + + " --hide UnflaggedApi" // TODO(b/297362755): TestApi lint doesn't ignore existing APIs. module_libs = " --show-annotation android.annotation.SystemApi\\(" + "client=android.annotation.SystemApi.Client.MODULE_LIBRARIES" + diff --git a/core/api/Android.bp b/core/api/Android.bp index 71a2ca2903f6..907916a125da 100644 --- a/core/api/Android.bp +++ b/core/api/Android.bp @@ -38,6 +38,11 @@ filegroup { } filegroup { + name: "non-updatable-lint-baseline.txt", + srcs: ["lint-baseline.txt"], +} + +filegroup { name: "non-updatable-system-current.txt", srcs: ["system-current.txt"], } diff --git a/core/api/current.txt b/core/api/current.txt index 8de8ab895962..d92c69346efd 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -15096,7 +15096,7 @@ package android.graphics { method public int getByteCount(); method @NonNull public android.graphics.Color getColor(int, int); method @Nullable public android.graphics.ColorSpace getColorSpace(); - method @NonNull public android.graphics.Bitmap.Config getConfig(); + method @Nullable public android.graphics.Bitmap.Config getConfig(); method public int getDensity(); method @Nullable public android.graphics.Gainmap getGainmap(); method public int getGenerationId(); @@ -38645,7 +38645,7 @@ package android.security { public final class FileIntegrityManager { method @FlaggedApi(Flags.FLAG_FSVERITY_API) @Nullable public byte[] getFsVerityDigest(@NonNull java.io.File) throws java.io.IOException; method public boolean isApkVeritySupported(); - method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public boolean isAppSourceCertificateTrusted(@NonNull java.security.cert.X509Certificate) throws java.security.cert.CertificateEncodingException; + method @RequiresPermission(anyOf={android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES}) public boolean isAppSourceCertificateTrusted(@NonNull java.security.cert.X509Certificate) throws java.security.cert.CertificateEncodingException; method @FlaggedApi(Flags.FLAG_FSVERITY_API) public void setupFsVerity(@NonNull java.io.File) throws java.io.IOException; } diff --git a/core/api/lint-baseline.txt b/core/api/lint-baseline.txt new file mode 100644 index 000000000000..6b7910afc347 --- /dev/null +++ b/core/api/lint-baseline.txt @@ -0,0 +1,521 @@ +// Baseline format: 1.0 +UnflaggedApi: android.accessibilityservice.AccessibilityService#OVERLAY_RESULT_INTERNAL_ERROR: + New API must be flagged with @FlaggedApi: field android.accessibilityservice.AccessibilityService.OVERLAY_RESULT_INTERNAL_ERROR +UnflaggedApi: android.accessibilityservice.AccessibilityService#OVERLAY_RESULT_INVALID: + New API must be flagged with @FlaggedApi: field android.accessibilityservice.AccessibilityService.OVERLAY_RESULT_INVALID +UnflaggedApi: android.accessibilityservice.AccessibilityService#OVERLAY_RESULT_SUCCESS: + New API must be flagged with @FlaggedApi: field android.accessibilityservice.AccessibilityService.OVERLAY_RESULT_SUCCESS +UnflaggedApi: android.accessibilityservice.AccessibilityService#attachAccessibilityOverlayToDisplay(int, android.view.SurfaceControl, java.util.concurrent.Executor, java.util.function.IntConsumer): + New API must be flagged with @FlaggedApi: method android.accessibilityservice.AccessibilityService.attachAccessibilityOverlayToDisplay(int,android.view.SurfaceControl,java.util.concurrent.Executor,java.util.function.IntConsumer) +UnflaggedApi: android.accessibilityservice.AccessibilityService#attachAccessibilityOverlayToWindow(int, android.view.SurfaceControl, java.util.concurrent.Executor, java.util.function.IntConsumer): + New API must be flagged with @FlaggedApi: method android.accessibilityservice.AccessibilityService.attachAccessibilityOverlayToWindow(int,android.view.SurfaceControl,java.util.concurrent.Executor,java.util.function.IntConsumer) +UnflaggedApi: android.app.Activity#onRequestPermissionsResult(int, String[], int[], int): + New API must be flagged with @FlaggedApi: method android.app.Activity.onRequestPermissionsResult(int,String[],int[],int) +UnflaggedApi: android.app.Activity#requestPermissions(String[], int, int): + New API must be flagged with @FlaggedApi: method android.app.Activity.requestPermissions(String[],int,int) +UnflaggedApi: android.app.Activity#setAllowCrossUidActivitySwitchFromBelow(boolean): + New API must be flagged with @FlaggedApi: method android.app.Activity.setAllowCrossUidActivitySwitchFromBelow(boolean) +UnflaggedApi: android.app.Activity#shouldShowRequestPermissionRationale(String, int): + New API must be flagged with @FlaggedApi: method android.app.Activity.shouldShowRequestPermissionRationale(String,int) +UnflaggedApi: android.app.ActivityManager#addStartInfoTimestamp(int, long): + New API must be flagged with @FlaggedApi: method android.app.ActivityManager.addStartInfoTimestamp(int,long) +UnflaggedApi: android.app.ActivityManager#clearApplicationStartInfoCompletionListener(): + New API must be flagged with @FlaggedApi: method android.app.ActivityManager.clearApplicationStartInfoCompletionListener() +UnflaggedApi: android.app.ActivityManager#getHistoricalProcessStartReasons(int): + New API must be flagged with @FlaggedApi: method android.app.ActivityManager.getHistoricalProcessStartReasons(int) +UnflaggedApi: android.app.ActivityManager#setApplicationStartInfoCompletionListener(java.util.concurrent.Executor, java.util.function.Consumer<android.app.ApplicationStartInfo>): + New API must be flagged with @FlaggedApi: method android.app.ActivityManager.setApplicationStartInfoCompletionListener(java.util.concurrent.Executor,java.util.function.Consumer<android.app.ApplicationStartInfo>) +UnflaggedApi: android.app.ApplicationStartInfo: + New API must be flagged with @FlaggedApi: class android.app.ApplicationStartInfo +UnflaggedApi: android.app.ApplicationStartInfo#CREATOR: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.CREATOR +UnflaggedApi: android.app.ApplicationStartInfo#LAUNCH_MODE_SINGLE_INSTANCE: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.LAUNCH_MODE_SINGLE_INSTANCE +UnflaggedApi: android.app.ApplicationStartInfo#LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.LAUNCH_MODE_SINGLE_INSTANCE_PER_TASK +UnflaggedApi: android.app.ApplicationStartInfo#LAUNCH_MODE_SINGLE_TASK: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.LAUNCH_MODE_SINGLE_TASK +UnflaggedApi: android.app.ApplicationStartInfo#LAUNCH_MODE_SINGLE_TOP: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.LAUNCH_MODE_SINGLE_TOP +UnflaggedApi: android.app.ApplicationStartInfo#LAUNCH_MODE_STANDARD: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.LAUNCH_MODE_STANDARD +UnflaggedApi: android.app.ApplicationStartInfo#STARTUP_STATE_ERROR: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.STARTUP_STATE_ERROR +UnflaggedApi: android.app.ApplicationStartInfo#STARTUP_STATE_FIRST_FRAME_DRAWN: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.STARTUP_STATE_FIRST_FRAME_DRAWN +UnflaggedApi: android.app.ApplicationStartInfo#STARTUP_STATE_STARTED: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.STARTUP_STATE_STARTED +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_ALARM: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_ALARM +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_BACKUP: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_BACKUP +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_BOOT_COMPLETE: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_BOOT_COMPLETE +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_BROADCAST: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_BROADCAST +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_CONTENT_PROVIDER: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_CONTENT_PROVIDER +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_JOB: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_JOB +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_LAUNCHER: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_LAUNCHER +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_LAUNCHER_RECENTS: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_LAUNCHER_RECENTS +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_OTHER: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_OTHER +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_PUSH: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_PUSH +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_SERVICE: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_SERVICE +UnflaggedApi: android.app.ApplicationStartInfo#START_REASON_START_ACTIVITY: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_REASON_START_ACTIVITY +UnflaggedApi: android.app.ApplicationStartInfo#START_TIMESTAMP_APPLICATION_ONCREATE: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TIMESTAMP_APPLICATION_ONCREATE +UnflaggedApi: android.app.ApplicationStartInfo#START_TIMESTAMP_BIND_APPLICATION: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TIMESTAMP_BIND_APPLICATION +UnflaggedApi: android.app.ApplicationStartInfo#START_TIMESTAMP_FIRST_FRAME: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TIMESTAMP_FIRST_FRAME +UnflaggedApi: android.app.ApplicationStartInfo#START_TIMESTAMP_FORK: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TIMESTAMP_FORK +UnflaggedApi: android.app.ApplicationStartInfo#START_TIMESTAMP_FULLY_DRAWN: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TIMESTAMP_FULLY_DRAWN +UnflaggedApi: android.app.ApplicationStartInfo#START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TIMESTAMP_INITIAL_RENDERTHREAD_FRAME +UnflaggedApi: android.app.ApplicationStartInfo#START_TIMESTAMP_LAUNCH: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TIMESTAMP_LAUNCH +UnflaggedApi: android.app.ApplicationStartInfo#START_TIMESTAMP_RESERVED_RANGE_DEVELOPER: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TIMESTAMP_RESERVED_RANGE_DEVELOPER +UnflaggedApi: android.app.ApplicationStartInfo#START_TIMESTAMP_RESERVED_RANGE_DEVELOPER_START: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TIMESTAMP_RESERVED_RANGE_DEVELOPER_START +UnflaggedApi: android.app.ApplicationStartInfo#START_TIMESTAMP_RESERVED_RANGE_SYSTEM: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TIMESTAMP_RESERVED_RANGE_SYSTEM +UnflaggedApi: android.app.ApplicationStartInfo#START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TIMESTAMP_SURFACEFLINGER_COMPOSITION_COMPLETE +UnflaggedApi: android.app.ApplicationStartInfo#START_TYPE_COLD: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TYPE_COLD +UnflaggedApi: android.app.ApplicationStartInfo#START_TYPE_HOT: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TYPE_HOT +UnflaggedApi: android.app.ApplicationStartInfo#START_TYPE_WARM: + New API must be flagged with @FlaggedApi: field android.app.ApplicationStartInfo.START_TYPE_WARM +UnflaggedApi: android.app.ApplicationStartInfo#describeContents(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.describeContents() +UnflaggedApi: android.app.ApplicationStartInfo#getDefiningUid(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.getDefiningUid() +UnflaggedApi: android.app.ApplicationStartInfo#getIntent(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.getIntent() +UnflaggedApi: android.app.ApplicationStartInfo#getLaunchMode(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.getLaunchMode() +UnflaggedApi: android.app.ApplicationStartInfo#getPackageUid(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.getPackageUid() +UnflaggedApi: android.app.ApplicationStartInfo#getPid(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.getPid() +UnflaggedApi: android.app.ApplicationStartInfo#getProcessName(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.getProcessName() +UnflaggedApi: android.app.ApplicationStartInfo#getRealUid(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.getRealUid() +UnflaggedApi: android.app.ApplicationStartInfo#getReason(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.getReason() +UnflaggedApi: android.app.ApplicationStartInfo#getStartType(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.getStartType() +UnflaggedApi: android.app.ApplicationStartInfo#getStartupState(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.getStartupState() +UnflaggedApi: android.app.ApplicationStartInfo#getStartupTimestamps(): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.getStartupTimestamps() +UnflaggedApi: android.app.ApplicationStartInfo#writeToParcel(android.os.Parcel, int): + New API must be flagged with @FlaggedApi: method android.app.ApplicationStartInfo.writeToParcel(android.os.Parcel,int) +UnflaggedApi: android.app.Notification.TvExtender: + New API must be flagged with @FlaggedApi: class android.app.Notification.TvExtender +UnflaggedApi: android.app.Notification.TvExtender#TvExtender(): + New API must be flagged with @FlaggedApi: constructor android.app.Notification.TvExtender() +UnflaggedApi: android.app.Notification.TvExtender#TvExtender(android.app.Notification): + New API must be flagged with @FlaggedApi: constructor android.app.Notification.TvExtender(android.app.Notification) +UnflaggedApi: android.app.Notification.TvExtender#extend(android.app.Notification.Builder): + New API must be flagged with @FlaggedApi: method android.app.Notification.TvExtender.extend(android.app.Notification.Builder) +UnflaggedApi: android.app.Notification.TvExtender#getChannelId(): + New API must be flagged with @FlaggedApi: method android.app.Notification.TvExtender.getChannelId() +UnflaggedApi: android.app.Notification.TvExtender#getContentIntent(): + New API must be flagged with @FlaggedApi: method android.app.Notification.TvExtender.getContentIntent() +UnflaggedApi: android.app.Notification.TvExtender#getDeleteIntent(): + New API must be flagged with @FlaggedApi: method android.app.Notification.TvExtender.getDeleteIntent() +UnflaggedApi: android.app.Notification.TvExtender#isAvailableOnTv(): + New API must be flagged with @FlaggedApi: method android.app.Notification.TvExtender.isAvailableOnTv() +UnflaggedApi: android.app.Notification.TvExtender#isSuppressShowOverApps(): + New API must be flagged with @FlaggedApi: method android.app.Notification.TvExtender.isSuppressShowOverApps() +UnflaggedApi: android.app.Notification.TvExtender#setChannelId(String): + New API must be flagged with @FlaggedApi: method android.app.Notification.TvExtender.setChannelId(String) +UnflaggedApi: android.app.Notification.TvExtender#setContentIntent(android.app.PendingIntent): + New API must be flagged with @FlaggedApi: method android.app.Notification.TvExtender.setContentIntent(android.app.PendingIntent) +UnflaggedApi: android.app.Notification.TvExtender#setDeleteIntent(android.app.PendingIntent): + New API must be flagged with @FlaggedApi: method android.app.Notification.TvExtender.setDeleteIntent(android.app.PendingIntent) +UnflaggedApi: android.app.Notification.TvExtender#setSuppressShowOverApps(boolean): + New API must be flagged with @FlaggedApi: method android.app.Notification.TvExtender.setSuppressShowOverApps(boolean) +UnflaggedApi: android.companion.AssociationInfo#getTag(): + New API must be flagged with @FlaggedApi: method android.companion.AssociationInfo.getTag() +UnflaggedApi: android.companion.CompanionDeviceManager#clearAssociationTag(int): + New API must be flagged with @FlaggedApi: method android.companion.CompanionDeviceManager.clearAssociationTag(int) +UnflaggedApi: android.companion.CompanionDeviceManager#setAssociationTag(int, String): + New API must be flagged with @FlaggedApi: method android.companion.CompanionDeviceManager.setAssociationTag(int,String) +UnflaggedApi: android.companion.CompanionDeviceService#DEVICE_EVENT_BLE_APPEARED: + New API must be flagged with @FlaggedApi: field android.companion.CompanionDeviceService.DEVICE_EVENT_BLE_APPEARED +UnflaggedApi: android.companion.CompanionDeviceService#DEVICE_EVENT_BLE_DISAPPEARED: + New API must be flagged with @FlaggedApi: field android.companion.CompanionDeviceService.DEVICE_EVENT_BLE_DISAPPEARED +UnflaggedApi: android.companion.CompanionDeviceService#DEVICE_EVENT_BT_CONNECTED: + New API must be flagged with @FlaggedApi: field android.companion.CompanionDeviceService.DEVICE_EVENT_BT_CONNECTED +UnflaggedApi: android.companion.CompanionDeviceService#DEVICE_EVENT_BT_DISCONNECTED: + New API must be flagged with @FlaggedApi: field android.companion.CompanionDeviceService.DEVICE_EVENT_BT_DISCONNECTED +UnflaggedApi: android.companion.CompanionDeviceService#DEVICE_EVENT_SELF_MANAGED_APPEARED: + New API must be flagged with @FlaggedApi: field android.companion.CompanionDeviceService.DEVICE_EVENT_SELF_MANAGED_APPEARED +UnflaggedApi: android.companion.CompanionDeviceService#DEVICE_EVENT_SELF_MANAGED_DISAPPEARED: + New API must be flagged with @FlaggedApi: field android.companion.CompanionDeviceService.DEVICE_EVENT_SELF_MANAGED_DISAPPEARED +UnflaggedApi: android.companion.CompanionDeviceService#onDeviceEvent(android.companion.AssociationInfo, int): + New API must be flagged with @FlaggedApi: method android.companion.CompanionDeviceService.onDeviceEvent(android.companion.AssociationInfo,int) +UnflaggedApi: android.companion.virtual.VirtualDevice#getPersistentDeviceId(): + New API must be flagged with @FlaggedApi: method android.companion.virtual.VirtualDevice.getPersistentDeviceId() +UnflaggedApi: android.companion.virtual.VirtualDeviceManager.VirtualDeviceListener#onVirtualDeviceClosed(int): + New API must be flagged with @FlaggedApi: method android.companion.virtual.VirtualDeviceManager.VirtualDeviceListener.onVirtualDeviceClosed(int) +UnflaggedApi: android.companion.virtual.VirtualDeviceManager.VirtualDeviceListener#onVirtualDeviceCreated(int): + New API must be flagged with @FlaggedApi: method android.companion.virtual.VirtualDeviceManager.VirtualDeviceListener.onVirtualDeviceCreated(int) +UnflaggedApi: android.content.AttributionSource#getDeviceId(): + New API must be flagged with @FlaggedApi: method android.content.AttributionSource.getDeviceId() +UnflaggedApi: android.content.AttributionSource.Builder#setDeviceId(int): + New API must be flagged with @FlaggedApi: method android.content.AttributionSource.Builder.setDeviceId(int) +UnflaggedApi: android.content.AttributionSource.Builder#setNextAttributionSource(android.content.AttributionSource): + New API must be flagged with @FlaggedApi: method android.content.AttributionSource.Builder.setNextAttributionSource(android.content.AttributionSource) +UnflaggedApi: android.content.ContextParams#shouldRegisterAttributionSource(): + New API must be flagged with @FlaggedApi: method android.content.ContextParams.shouldRegisterAttributionSource() +UnflaggedApi: android.content.ContextParams.Builder#setShouldRegisterAttributionSource(boolean): + New API must be flagged with @FlaggedApi: method android.content.ContextParams.Builder.setShouldRegisterAttributionSource(boolean) +UnflaggedApi: android.content.Intent#EXTRA_ARCHIVAL: + New API must be flagged with @FlaggedApi: field android.content.Intent.EXTRA_ARCHIVAL +UnflaggedApi: android.content.om.FabricatedOverlay#setResourceValue(String, android.content.res.AssetFileDescriptor, String): + New API must be flagged with @FlaggedApi: method android.content.om.FabricatedOverlay.setResourceValue(String,android.content.res.AssetFileDescriptor,String) +UnflaggedApi: android.content.pm.PackageManager#FEATURE_THREAD_NETWORK: + New API must be flagged with @FlaggedApi: field android.content.pm.PackageManager.FEATURE_THREAD_NETWORK +UnflaggedApi: android.database.sqlite.SQLiteDatabase#beginTransactionReadOnly(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteDatabase.beginTransactionReadOnly() +UnflaggedApi: android.database.sqlite.SQLiteDatabase#beginTransactionWithListenerReadOnly(android.database.sqlite.SQLiteTransactionListener): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteDatabase.beginTransactionWithListenerReadOnly(android.database.sqlite.SQLiteTransactionListener) +UnflaggedApi: android.database.sqlite.SQLiteDatabase#createRawStatement(String): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteDatabase.createRawStatement(String) +UnflaggedApi: android.database.sqlite.SQLiteDatabase#getLastChangedRowCount(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteDatabase.getLastChangedRowCount() +UnflaggedApi: android.database.sqlite.SQLiteDatabase#getLastInsertRowId(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteDatabase.getLastInsertRowId() +UnflaggedApi: android.database.sqlite.SQLiteDatabase#getTotalChangedRowCount(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteDatabase.getTotalChangedRowCount() +UnflaggedApi: android.database.sqlite.SQLiteRawStatement: + New API must be flagged with @FlaggedApi: class android.database.sqlite.SQLiteRawStatement +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#SQLITE_DATA_TYPE_BLOB: + New API must be flagged with @FlaggedApi: field android.database.sqlite.SQLiteRawStatement.SQLITE_DATA_TYPE_BLOB +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#SQLITE_DATA_TYPE_FLOAT: + New API must be flagged with @FlaggedApi: field android.database.sqlite.SQLiteRawStatement.SQLITE_DATA_TYPE_FLOAT +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#SQLITE_DATA_TYPE_INTEGER: + New API must be flagged with @FlaggedApi: field android.database.sqlite.SQLiteRawStatement.SQLITE_DATA_TYPE_INTEGER +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#SQLITE_DATA_TYPE_NULL: + New API must be flagged with @FlaggedApi: field android.database.sqlite.SQLiteRawStatement.SQLITE_DATA_TYPE_NULL +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#SQLITE_DATA_TYPE_TEXT: + New API must be flagged with @FlaggedApi: field android.database.sqlite.SQLiteRawStatement.SQLITE_DATA_TYPE_TEXT +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#bindBlob(int, byte[]): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.bindBlob(int,byte[]) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#bindBlob(int, byte[], int, int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.bindBlob(int,byte[],int,int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#bindDouble(int, double): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.bindDouble(int,double) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#bindInt(int, int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.bindInt(int,int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#bindLong(int, long): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.bindLong(int,long) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#bindNull(int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.bindNull(int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#bindText(int, String): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.bindText(int,String) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#clearBindings(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.clearBindings() +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#close(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.close() +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getColumnBlob(int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getColumnBlob(int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getColumnDouble(int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getColumnDouble(int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getColumnInt(int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getColumnInt(int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getColumnLength(int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getColumnLength(int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getColumnLong(int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getColumnLong(int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getColumnName(int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getColumnName(int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getColumnText(int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getColumnText(int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getColumnType(int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getColumnType(int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getParameterCount(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getParameterCount() +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getParameterIndex(String): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getParameterIndex(String) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getParameterName(int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getParameterName(int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#getResultColumnCount(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.getResultColumnCount() +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#isOpen(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.isOpen() +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#readColumnBlob(int, byte[], int, int, int): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.readColumnBlob(int,byte[],int,int,int) +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#reset(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.reset() +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#step(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.step() +UnflaggedApi: android.database.sqlite.SQLiteRawStatement#toString(): + New API must be flagged with @FlaggedApi: method android.database.sqlite.SQLiteRawStatement.toString() +UnflaggedApi: android.graphics.Gainmap#Gainmap(android.graphics.Gainmap, android.graphics.Bitmap): + New API must be flagged with @FlaggedApi: constructor android.graphics.Gainmap(android.graphics.Gainmap,android.graphics.Bitmap) +UnflaggedApi: android.graphics.Path#computeBounds(android.graphics.RectF): + New API must be flagged with @FlaggedApi: method android.graphics.Path.computeBounds(android.graphics.RectF) +UnflaggedApi: android.graphics.fonts.FontFamily.Builder#buildVariableFamily(): + New API must be flagged with @FlaggedApi: method android.graphics.fonts.FontFamily.Builder.buildVariableFamily() +UnflaggedApi: android.graphics.text.LineBreakConfig#LINE_BREAK_STYLE_UNSPECIFIED: + New API must be flagged with @FlaggedApi: field android.graphics.text.LineBreakConfig.LINE_BREAK_STYLE_UNSPECIFIED +UnflaggedApi: android.graphics.text.LineBreakConfig#LINE_BREAK_WORD_STYLE_UNSPECIFIED: + New API must be flagged with @FlaggedApi: field android.graphics.text.LineBreakConfig.LINE_BREAK_WORD_STYLE_UNSPECIFIED +UnflaggedApi: android.graphics.text.LineBreakConfig#merge(android.graphics.text.LineBreakConfig): + New API must be flagged with @FlaggedApi: method android.graphics.text.LineBreakConfig.merge(android.graphics.text.LineBreakConfig) +UnflaggedApi: android.graphics.text.LineBreakConfig.Builder#merge(android.graphics.text.LineBreakConfig): + New API must be flagged with @FlaggedApi: method android.graphics.text.LineBreakConfig.Builder.merge(android.graphics.text.LineBreakConfig) +UnflaggedApi: android.graphics.text.LineBreaker.Builder#setUseBoundsForWidth(boolean): + New API must be flagged with @FlaggedApi: method android.graphics.text.LineBreaker.Builder.setUseBoundsForWidth(boolean) +UnflaggedApi: android.graphics.text.PositionedGlyphs#NO_OVERRIDE: + New API must be flagged with @FlaggedApi: field android.graphics.text.PositionedGlyphs.NO_OVERRIDE +UnflaggedApi: android.graphics.text.PositionedGlyphs#getFakeBold(int): + New API must be flagged with @FlaggedApi: method android.graphics.text.PositionedGlyphs.getFakeBold(int) +UnflaggedApi: android.graphics.text.PositionedGlyphs#getFakeItalic(int): + New API must be flagged with @FlaggedApi: method android.graphics.text.PositionedGlyphs.getFakeItalic(int) +UnflaggedApi: android.graphics.text.PositionedGlyphs#getItalicOverride(int): + New API must be flagged with @FlaggedApi: method android.graphics.text.PositionedGlyphs.getItalicOverride(int) +UnflaggedApi: android.graphics.text.PositionedGlyphs#getWeightOverride(int): + New API must be flagged with @FlaggedApi: method android.graphics.text.PositionedGlyphs.getWeightOverride(int) +UnflaggedApi: android.media.MediaRoute2Info#TYPE_REMOTE_CAR: + New API must be flagged with @FlaggedApi: field android.media.MediaRoute2Info.TYPE_REMOTE_CAR +UnflaggedApi: android.media.MediaRoute2Info#TYPE_REMOTE_COMPUTER: + New API must be flagged with @FlaggedApi: field android.media.MediaRoute2Info.TYPE_REMOTE_COMPUTER +UnflaggedApi: android.media.MediaRoute2Info#TYPE_REMOTE_GAME_CONSOLE: + New API must be flagged with @FlaggedApi: field android.media.MediaRoute2Info.TYPE_REMOTE_GAME_CONSOLE +UnflaggedApi: android.media.MediaRoute2Info#TYPE_REMOTE_SMARTPHONE: + New API must be flagged with @FlaggedApi: field android.media.MediaRoute2Info.TYPE_REMOTE_SMARTPHONE +UnflaggedApi: android.media.MediaRoute2Info#TYPE_REMOTE_SMARTWATCH: + New API must be flagged with @FlaggedApi: field android.media.MediaRoute2Info.TYPE_REMOTE_SMARTWATCH +UnflaggedApi: android.media.MediaRoute2Info#TYPE_REMOTE_TABLET: + New API must be flagged with @FlaggedApi: field android.media.MediaRoute2Info.TYPE_REMOTE_TABLET +UnflaggedApi: android.media.MediaRoute2Info#TYPE_REMOTE_TABLET_DOCKED: + New API must be flagged with @FlaggedApi: field android.media.MediaRoute2Info.TYPE_REMOTE_TABLET_DOCKED +UnflaggedApi: android.media.midi.MidiUmpDeviceService: + New API must be flagged with @FlaggedApi: class android.media.midi.MidiUmpDeviceService +UnflaggedApi: android.media.midi.MidiUmpDeviceService#MidiUmpDeviceService(): + New API must be flagged with @FlaggedApi: constructor android.media.midi.MidiUmpDeviceService() +UnflaggedApi: android.media.midi.MidiUmpDeviceService#SERVICE_INTERFACE: + New API must be flagged with @FlaggedApi: field android.media.midi.MidiUmpDeviceService.SERVICE_INTERFACE +UnflaggedApi: android.media.midi.MidiUmpDeviceService#getDeviceInfo(): + New API must be flagged with @FlaggedApi: method android.media.midi.MidiUmpDeviceService.getDeviceInfo() +UnflaggedApi: android.media.midi.MidiUmpDeviceService#getOutputPortReceivers(): + New API must be flagged with @FlaggedApi: method android.media.midi.MidiUmpDeviceService.getOutputPortReceivers() +UnflaggedApi: android.media.midi.MidiUmpDeviceService#onBind(android.content.Intent): + New API must be flagged with @FlaggedApi: method android.media.midi.MidiUmpDeviceService.onBind(android.content.Intent) +UnflaggedApi: android.media.midi.MidiUmpDeviceService#onClose(): + New API must be flagged with @FlaggedApi: method android.media.midi.MidiUmpDeviceService.onClose() +UnflaggedApi: android.media.midi.MidiUmpDeviceService#onCreate(): + New API must be flagged with @FlaggedApi: method android.media.midi.MidiUmpDeviceService.onCreate() +UnflaggedApi: android.media.midi.MidiUmpDeviceService#onDeviceStatusChanged(android.media.midi.MidiDeviceStatus): + New API must be flagged with @FlaggedApi: method android.media.midi.MidiUmpDeviceService.onDeviceStatusChanged(android.media.midi.MidiDeviceStatus) +UnflaggedApi: android.media.midi.MidiUmpDeviceService#onGetInputPortReceivers(): + New API must be flagged with @FlaggedApi: method android.media.midi.MidiUmpDeviceService.onGetInputPortReceivers() +UnflaggedApi: android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM: + New API must be flagged with @FlaggedApi: field android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM +UnflaggedApi: android.os.PerformanceHintManager.Session#setPreferPowerEfficiency(boolean): + New API must be flagged with @FlaggedApi: method android.os.PerformanceHintManager.Session.setPreferPowerEfficiency(boolean) +UnflaggedApi: android.os.UserManager#DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO: + New API must be flagged with @FlaggedApi: field android.os.UserManager.DISALLOW_NEAR_FIELD_COMMUNICATION_RADIO +UnflaggedApi: android.provider.Settings#ACTION_CREDENTIAL_PROVIDER: + New API must be flagged with @FlaggedApi: field android.provider.Settings.ACTION_CREDENTIAL_PROVIDER +UnflaggedApi: android.telecom.Call.Details#PROPERTY_IS_TRANSACTIONAL: + New API must be flagged with @FlaggedApi: field android.telecom.Call.Details.PROPERTY_IS_TRANSACTIONAL +UnflaggedApi: android.telecom.Call.Details#getId(): + New API must be flagged with @FlaggedApi: method android.telecom.Call.Details.getId() +UnflaggedApi: android.telephony.CarrierConfigManager#KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE: + New API must be flagged with @FlaggedApi: field android.telephony.CarrierConfigManager.KEY_CARRIER_SUPPORTED_SATELLITE_SERVICES_PER_PROVIDER_BUNDLE +UnflaggedApi: android.telephony.DisconnectCause#SATELLITE_ENABLED: + New API must be flagged with @FlaggedApi: field android.telephony.DisconnectCause.SATELLITE_ENABLED +UnflaggedApi: android.telephony.NetworkRegistrationInfo#SERVICE_TYPE_MMS: + New API must be flagged with @FlaggedApi: field android.telephony.NetworkRegistrationInfo.SERVICE_TYPE_MMS +UnflaggedApi: android.telephony.NetworkRegistrationInfo#isNonTerrestrialNetwork(): + New API must be flagged with @FlaggedApi: method android.telephony.NetworkRegistrationInfo.isNonTerrestrialNetwork() +UnflaggedApi: android.telephony.PhoneNumberUtils#isWpsCallNumber(String): + New API must be flagged with @FlaggedApi: method android.telephony.PhoneNumberUtils.isWpsCallNumber(String) +UnflaggedApi: android.telephony.ServiceState#isUsingNonTerrestrialNetwork(): + New API must be flagged with @FlaggedApi: method android.telephony.ServiceState.isUsingNonTerrestrialNetwork() +UnflaggedApi: android.telephony.TelephonyManager#EVENT_DISPLAY_SOS_MESSAGE: + New API must be flagged with @FlaggedApi: field android.telephony.TelephonyManager.EVENT_DISPLAY_SOS_MESSAGE +UnflaggedApi: android.telephony.TelephonyManager#PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED: + New API must be flagged with @FlaggedApi: field android.telephony.TelephonyManager.PURCHASE_PREMIUM_CAPABILITY_RESULT_USER_DISABLED +UnflaggedApi: android.text.BoringLayout#computeDrawingBoundingBox(): + New API must be flagged with @FlaggedApi: method android.text.BoringLayout.computeDrawingBoundingBox() +UnflaggedApi: android.text.BoringLayout.Metrics#getDrawingBoundingBox(): + New API must be flagged with @FlaggedApi: method android.text.BoringLayout.Metrics.getDrawingBoundingBox() +UnflaggedApi: android.text.DynamicLayout#getLineBreakConfig(): + New API must be flagged with @FlaggedApi: method android.text.DynamicLayout.getLineBreakConfig() +UnflaggedApi: android.text.DynamicLayout.Builder#setLineBreakConfig(android.graphics.text.LineBreakConfig): + New API must be flagged with @FlaggedApi: method android.text.DynamicLayout.Builder.setLineBreakConfig(android.graphics.text.LineBreakConfig) +UnflaggedApi: android.text.DynamicLayout.Builder#setUseBoundsForWidth(boolean): + New API must be flagged with @FlaggedApi: method android.text.DynamicLayout.Builder.setUseBoundsForWidth(boolean) +UnflaggedApi: android.text.Layout#computeDrawingBoundingBox(): + New API must be flagged with @FlaggedApi: method android.text.Layout.computeDrawingBoundingBox() +UnflaggedApi: android.text.Layout#getBreakStrategy(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getBreakStrategy() +UnflaggedApi: android.text.Layout#getEllipsize(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getEllipsize() +UnflaggedApi: android.text.Layout#getHyphenationFrequency(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getHyphenationFrequency() +UnflaggedApi: android.text.Layout#getJustificationMode(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getJustificationMode() +UnflaggedApi: android.text.Layout#getLeftIndents(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getLeftIndents() +UnflaggedApi: android.text.Layout#getLineBreakConfig(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getLineBreakConfig() +UnflaggedApi: android.text.Layout#getLineSpacingAmount(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getLineSpacingAmount() +UnflaggedApi: android.text.Layout#getLineSpacingMultiplier(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getLineSpacingMultiplier() +UnflaggedApi: android.text.Layout#getMaxLines(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getMaxLines() +UnflaggedApi: android.text.Layout#getRightIndents(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getRightIndents() +UnflaggedApi: android.text.Layout#getTextDirectionHeuristic(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getTextDirectionHeuristic() +UnflaggedApi: android.text.Layout#getUseBoundsForWidth(): + New API must be flagged with @FlaggedApi: method android.text.Layout.getUseBoundsForWidth() +UnflaggedApi: android.text.Layout#isFontPaddingIncluded(): + New API must be flagged with @FlaggedApi: method android.text.Layout.isFontPaddingIncluded() +UnflaggedApi: android.text.Layout.Builder: + New API must be flagged with @FlaggedApi: class android.text.Layout.Builder +UnflaggedApi: android.text.Layout.Builder#Builder(CharSequence, int, int, android.text.TextPaint, int): + New API must be flagged with @FlaggedApi: constructor android.text.Layout.Builder(CharSequence,int,int,android.text.TextPaint,int) +UnflaggedApi: android.text.Layout.Builder#build(): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.build() +UnflaggedApi: android.text.Layout.Builder#setAlignment(android.text.Layout.Alignment): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setAlignment(android.text.Layout.Alignment) +UnflaggedApi: android.text.Layout.Builder#setBreakStrategy(int): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setBreakStrategy(int) +UnflaggedApi: android.text.Layout.Builder#setEllipsize(android.text.TextUtils.TruncateAt): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setEllipsize(android.text.TextUtils.TruncateAt) +UnflaggedApi: android.text.Layout.Builder#setEllipsizedWidth(int): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setEllipsizedWidth(int) +UnflaggedApi: android.text.Layout.Builder#setFallbackLineSpacingEnabled(boolean): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setFallbackLineSpacingEnabled(boolean) +UnflaggedApi: android.text.Layout.Builder#setFontPaddingIncluded(boolean): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setFontPaddingIncluded(boolean) +UnflaggedApi: android.text.Layout.Builder#setHyphenationFrequency(int): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setHyphenationFrequency(int) +UnflaggedApi: android.text.Layout.Builder#setJustificationMode(int): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setJustificationMode(int) +UnflaggedApi: android.text.Layout.Builder#setLeftIndents(int[]): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setLeftIndents(int[]) +UnflaggedApi: android.text.Layout.Builder#setLineBreakConfig(android.graphics.text.LineBreakConfig): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setLineBreakConfig(android.graphics.text.LineBreakConfig) +UnflaggedApi: android.text.Layout.Builder#setLineSpacingAmount(float): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setLineSpacingAmount(float) +UnflaggedApi: android.text.Layout.Builder#setLineSpacingMultiplier(float): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setLineSpacingMultiplier(float) +UnflaggedApi: android.text.Layout.Builder#setMaxLines(int): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setMaxLines(int) +UnflaggedApi: android.text.Layout.Builder#setRightIndents(int[]): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setRightIndents(int[]) +UnflaggedApi: android.text.Layout.Builder#setTextDirectionHeuristic(android.text.TextDirectionHeuristic): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setTextDirectionHeuristic(android.text.TextDirectionHeuristic) +UnflaggedApi: android.text.Layout.Builder#setUseBoundsForWidth(boolean): + New API must be flagged with @FlaggedApi: method android.text.Layout.Builder.setUseBoundsForWidth(boolean) +UnflaggedApi: android.text.StaticLayout#computeDrawingBoundingBox(): + New API must be flagged with @FlaggedApi: method android.text.StaticLayout.computeDrawingBoundingBox() +UnflaggedApi: android.text.StaticLayout.Builder#setUseBoundsForWidth(boolean): + New API must be flagged with @FlaggedApi: method android.text.StaticLayout.Builder.setUseBoundsForWidth(boolean) +UnflaggedApi: android.text.style.LineBreakConfigSpan: + New API must be flagged with @FlaggedApi: class android.text.style.LineBreakConfigSpan +UnflaggedApi: android.text.style.LineBreakConfigSpan#LineBreakConfigSpan(android.graphics.text.LineBreakConfig): + New API must be flagged with @FlaggedApi: constructor android.text.style.LineBreakConfigSpan(android.graphics.text.LineBreakConfig) +UnflaggedApi: android.text.style.LineBreakConfigSpan#equals(Object): + New API must be flagged with @FlaggedApi: method android.text.style.LineBreakConfigSpan.equals(Object) +UnflaggedApi: android.text.style.LineBreakConfigSpan#getLineBreakConfig(): + New API must be flagged with @FlaggedApi: method android.text.style.LineBreakConfigSpan.getLineBreakConfig() +UnflaggedApi: android.text.style.LineBreakConfigSpan#hashCode(): + New API must be flagged with @FlaggedApi: method android.text.style.LineBreakConfigSpan.hashCode() +UnflaggedApi: android.text.style.LineBreakConfigSpan#toString(): + New API must be flagged with @FlaggedApi: method android.text.style.LineBreakConfigSpan.toString() +UnflaggedApi: android.view.HapticScrollFeedbackProvider#HapticScrollFeedbackProvider(android.view.View): + New API must be flagged with @FlaggedApi: constructor android.view.HapticScrollFeedbackProvider(android.view.View) +UnflaggedApi: android.view.HapticScrollFeedbackProvider#onScrollLimit(int, int, int, boolean): + New API must be flagged with @FlaggedApi: method android.view.HapticScrollFeedbackProvider.onScrollLimit(int,int,int,boolean) +UnflaggedApi: android.view.HapticScrollFeedbackProvider#onScrollProgress(int, int, int, int): + New API must be flagged with @FlaggedApi: method android.view.HapticScrollFeedbackProvider.onScrollProgress(int,int,int,int) +UnflaggedApi: android.view.HapticScrollFeedbackProvider#onSnapToItem(int, int, int): + New API must be flagged with @FlaggedApi: method android.view.HapticScrollFeedbackProvider.onSnapToItem(int,int,int) +UnflaggedApi: android.view.ScrollFeedbackProvider#onScrollLimit(android.view.MotionEvent, int, boolean): + New API must be flagged with @FlaggedApi: method android.view.ScrollFeedbackProvider.onScrollLimit(android.view.MotionEvent,int,boolean) +UnflaggedApi: android.view.ScrollFeedbackProvider#onScrollLimit(int, int, int, boolean): + New API must be flagged with @FlaggedApi: method android.view.ScrollFeedbackProvider.onScrollLimit(int,int,int,boolean) +UnflaggedApi: android.view.ScrollFeedbackProvider#onScrollProgress(android.view.MotionEvent, int, int): + New API must be flagged with @FlaggedApi: method android.view.ScrollFeedbackProvider.onScrollProgress(android.view.MotionEvent,int,int) +UnflaggedApi: android.view.ScrollFeedbackProvider#onScrollProgress(int, int, int, int): + New API must be flagged with @FlaggedApi: method android.view.ScrollFeedbackProvider.onScrollProgress(int,int,int,int) +UnflaggedApi: android.view.ScrollFeedbackProvider#onSnapToItem(android.view.MotionEvent, int): + New API must be flagged with @FlaggedApi: method android.view.ScrollFeedbackProvider.onSnapToItem(android.view.MotionEvent,int) +UnflaggedApi: android.view.ScrollFeedbackProvider#onSnapToItem(int, int, int): + New API must be flagged with @FlaggedApi: method android.view.ScrollFeedbackProvider.onSnapToItem(int,int,int) +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo#ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT: + New API must be flagged with @FlaggedApi: field android.view.accessibility.AccessibilityNodeInfo.ACTION_ARGUMENT_SCROLL_AMOUNT_FLOAT +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo#isGranularScrollingSupported(): + New API must be flagged with @FlaggedApi: method android.view.accessibility.AccessibilityNodeInfo.isGranularScrollingSupported() +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo#setGranularScrollingSupported(boolean): + New API must be flagged with @FlaggedApi: method android.view.accessibility.AccessibilityNodeInfo.setGranularScrollingSupported(boolean) +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo#CollectionInfo(int, int, boolean, int, int, int): + New API must be flagged with @FlaggedApi: constructor android.view.accessibility.AccessibilityNodeInfo.CollectionInfo(int,int,boolean,int,int,int) +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo#UNDEFINED: + New API must be flagged with @FlaggedApi: field android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.UNDEFINED +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo#getImportantForAccessibilityItemCount(): + New API must be flagged with @FlaggedApi: method android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.getImportantForAccessibilityItemCount() +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo#getItemCount(): + New API must be flagged with @FlaggedApi: method android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.getItemCount() +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder: + New API must be flagged with @FlaggedApi: class android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder#Builder(): + New API must be flagged with @FlaggedApi: constructor android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder() +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder#build(): + New API must be flagged with @FlaggedApi: method android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder.build() +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder#setColumnCount(int): + New API must be flagged with @FlaggedApi: method android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder.setColumnCount(int) +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder#setHierarchical(boolean): + New API must be flagged with @FlaggedApi: method android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder.setHierarchical(boolean) +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder#setImportantForAccessibilityItemCount(int): + New API must be flagged with @FlaggedApi: method android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder.setImportantForAccessibilityItemCount(int) +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder#setItemCount(int): + New API must be flagged with @FlaggedApi: method android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder.setItemCount(int) +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder#setRowCount(int): + New API must be flagged with @FlaggedApi: method android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder.setRowCount(int) +UnflaggedApi: android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder#setSelectionMode(int): + New API must be flagged with @FlaggedApi: method android.view.accessibility.AccessibilityNodeInfo.CollectionInfo.Builder.setSelectionMode(int) +UnflaggedApi: android.view.animation.AnimationUtils#getExpectedPresentationTimeMillis(): + New API must be flagged with @FlaggedApi: method android.view.animation.AnimationUtils.getExpectedPresentationTimeMillis() +UnflaggedApi: android.view.animation.AnimationUtils#getExpectedPresentationTimeNanos(): + New API must be flagged with @FlaggedApi: method android.view.animation.AnimationUtils.getExpectedPresentationTimeNanos() +UnflaggedApi: android.view.autofill.AutofillManager#clearAutofillRequestCallback(): + New API must be flagged with @FlaggedApi: method android.view.autofill.AutofillManager.clearAutofillRequestCallback() +UnflaggedApi: android.view.autofill.AutofillManager#setAutofillRequestCallback(java.util.concurrent.Executor, android.view.autofill.AutofillRequestCallback): + New API must be flagged with @FlaggedApi: method android.view.autofill.AutofillManager.setAutofillRequestCallback(java.util.concurrent.Executor,android.view.autofill.AutofillRequestCallback) +UnflaggedApi: android.view.autofill.AutofillRequestCallback: + New API must be flagged with @FlaggedApi: class android.view.autofill.AutofillRequestCallback +UnflaggedApi: android.view.autofill.AutofillRequestCallback#onFillRequest(android.view.inputmethod.InlineSuggestionsRequest, android.os.CancellationSignal, android.service.autofill.FillCallback): + New API must be flagged with @FlaggedApi: method android.view.autofill.AutofillRequestCallback.onFillRequest(android.view.inputmethod.InlineSuggestionsRequest,android.os.CancellationSignal,android.service.autofill.FillCallback) +UnflaggedApi: android.view.inputmethod.InlineSuggestionsRequest.Builder#setClientSupported(boolean): + New API must be flagged with @FlaggedApi: method android.view.inputmethod.InlineSuggestionsRequest.Builder.setClientSupported(boolean) +UnflaggedApi: android.view.inputmethod.InlineSuggestionsRequest.Builder#setServiceSupported(boolean): + New API must be flagged with @FlaggedApi: method android.view.inputmethod.InlineSuggestionsRequest.Builder.setServiceSupported(boolean) +UnflaggedApi: android.widget.TextView#getUseBoundsForWidth(): + New API must be flagged with @FlaggedApi: method android.widget.TextView.getUseBoundsForWidth() +UnflaggedApi: android.widget.TextView#setUseBoundsForWidth(boolean): + New API must be flagged with @FlaggedApi: method android.widget.TextView.setUseBoundsForWidth(boolean) diff --git a/core/api/module-lib-lint-baseline.txt b/core/api/module-lib-lint-baseline.txt index 471745ae0c50..a0d38588bc10 100644 --- a/core/api/module-lib-lint-baseline.txt +++ b/core/api/module-lib-lint-baseline.txt @@ -45,3 +45,57 @@ SamShouldBeLast: android.os.IBinder#linkToDeath(android.os.IBinder.DeathRecipien SAM-compatible parameters (such as parameter 1, "recipient", in android.os.IBinder.linkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions SamShouldBeLast: android.os.IBinder#unlinkToDeath(android.os.IBinder.DeathRecipient, int): SAM-compatible parameters (such as parameter 1, "recipient", in android.os.IBinder.unlinkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions + + +UnflaggedApi: android.Manifest.permission#BLUETOOTH_STACK: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BLUETOOTH_STACK +UnflaggedApi: android.Manifest.permission#CONTROL_AUTOMOTIVE_GNSS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CONTROL_AUTOMOTIVE_GNSS +UnflaggedApi: android.Manifest.permission#GET_INTENT_SENDER_INTENT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.GET_INTENT_SENDER_INTENT +UnflaggedApi: android.Manifest.permission#MAKE_UID_VISIBLE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MAKE_UID_VISIBLE +UnflaggedApi: android.Manifest.permission#MANAGE_REMOTE_AUTH: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_REMOTE_AUTH +UnflaggedApi: android.Manifest.permission#USE_COMPANION_TRANSPORTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.USE_COMPANION_TRANSPORTS +UnflaggedApi: android.Manifest.permission#USE_REMOTE_AUTH: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.USE_REMOTE_AUTH +UnflaggedApi: android.app.Activity#isResumed(): + New API must be flagged with @FlaggedApi: method android.app.Activity.isResumed() +UnflaggedApi: android.companion.CompanionDeviceManager#MESSAGE_REQUEST_CONTEXT_SYNC: + New API must be flagged with @FlaggedApi: field android.companion.CompanionDeviceManager.MESSAGE_REQUEST_CONTEXT_SYNC +UnflaggedApi: android.companion.CompanionDeviceManager#MESSAGE_REQUEST_PERMISSION_RESTORE: + New API must be flagged with @FlaggedApi: field android.companion.CompanionDeviceManager.MESSAGE_REQUEST_PERMISSION_RESTORE +UnflaggedApi: android.companion.CompanionDeviceManager#MESSAGE_REQUEST_REMOTE_AUTHENTICATION: + New API must be flagged with @FlaggedApi: field android.companion.CompanionDeviceManager.MESSAGE_REQUEST_REMOTE_AUTHENTICATION +UnflaggedApi: android.companion.CompanionDeviceManager#addOnMessageReceivedListener(java.util.concurrent.Executor, int, android.companion.CompanionDeviceManager.OnMessageReceivedListener): + New API must be flagged with @FlaggedApi: method android.companion.CompanionDeviceManager.addOnMessageReceivedListener(java.util.concurrent.Executor,int,android.companion.CompanionDeviceManager.OnMessageReceivedListener) +UnflaggedApi: android.companion.CompanionDeviceManager#addOnTransportsChangedListener(java.util.concurrent.Executor, android.companion.CompanionDeviceManager.OnTransportsChangedListener): + New API must be flagged with @FlaggedApi: method android.companion.CompanionDeviceManager.addOnTransportsChangedListener(java.util.concurrent.Executor,android.companion.CompanionDeviceManager.OnTransportsChangedListener) +UnflaggedApi: android.companion.CompanionDeviceManager#removeOnMessageReceivedListener(int, android.companion.CompanionDeviceManager.OnMessageReceivedListener): + New API must be flagged with @FlaggedApi: method android.companion.CompanionDeviceManager.removeOnMessageReceivedListener(int,android.companion.CompanionDeviceManager.OnMessageReceivedListener) +UnflaggedApi: android.companion.CompanionDeviceManager#removeOnTransportsChangedListener(android.companion.CompanionDeviceManager.OnTransportsChangedListener): + New API must be flagged with @FlaggedApi: method android.companion.CompanionDeviceManager.removeOnTransportsChangedListener(android.companion.CompanionDeviceManager.OnTransportsChangedListener) +UnflaggedApi: android.companion.CompanionDeviceManager#sendMessage(int, byte[], int[]): + New API must be flagged with @FlaggedApi: method android.companion.CompanionDeviceManager.sendMessage(int,byte[],int[]) +UnflaggedApi: android.companion.CompanionDeviceManager.OnMessageReceivedListener: + New API must be flagged with @FlaggedApi: class android.companion.CompanionDeviceManager.OnMessageReceivedListener +UnflaggedApi: android.companion.CompanionDeviceManager.OnMessageReceivedListener#onMessageReceived(int, byte[]): + New API must be flagged with @FlaggedApi: method android.companion.CompanionDeviceManager.OnMessageReceivedListener.onMessageReceived(int,byte[]) +UnflaggedApi: android.companion.CompanionDeviceManager.OnTransportsChangedListener: + New API must be flagged with @FlaggedApi: class android.companion.CompanionDeviceManager.OnTransportsChangedListener +UnflaggedApi: android.companion.CompanionDeviceManager.OnTransportsChangedListener#onTransportsChanged(java.util.List<android.companion.AssociationInfo>): + New API must be flagged with @FlaggedApi: method android.companion.CompanionDeviceManager.OnTransportsChangedListener.onTransportsChanged(java.util.List<android.companion.AssociationInfo>) +UnflaggedApi: android.content.Context#REMOTE_AUTH_SERVICE: + New API must be flagged with @FlaggedApi: field android.content.Context.REMOTE_AUTH_SERVICE +UnflaggedApi: android.content.ContextWrapper#createContextForSdkInSandbox(android.content.pm.ApplicationInfo, int): + New API must be flagged with @FlaggedApi: method android.content.ContextWrapper.createContextForSdkInSandbox(android.content.pm.ApplicationInfo,int) +UnflaggedApi: android.media.session.MediaController.PlaybackInfo#PlaybackInfo(int, int, int, int, android.media.AudioAttributes, String): + New API must be flagged with @FlaggedApi: constructor android.media.session.MediaController.PlaybackInfo(int,int,int,int,android.media.AudioAttributes,String) +UnflaggedApi: android.os.IpcDataCache#MODULE_TELEPHONY: + New API must be flagged with @FlaggedApi: field android.os.IpcDataCache.MODULE_TELEPHONY +UnflaggedApi: android.provider.ContactsContract.RawContactsEntity#queryRawContactEntity(android.content.ContentResolver, long): + New API must be flagged with @FlaggedApi: method android.provider.ContactsContract.RawContactsEntity.queryRawContactEntity(android.content.ContentResolver,long) +UnflaggedApi: android.provider.Settings.Config#getAllStrings(): + New API must be flagged with @FlaggedApi: method android.provider.Settings.Config.getAllStrings() diff --git a/core/api/system-current.txt b/core/api/system-current.txt index ff44a1b87e18..a5e69abeb9d3 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -12654,7 +12654,7 @@ package android.service.voice { method @NonNull public android.service.voice.HotwordTrainingAudio build(); method @NonNull public android.service.voice.HotwordTrainingAudio.Builder setAudioFormat(@NonNull android.media.AudioFormat); method @NonNull public android.service.voice.HotwordTrainingAudio.Builder setAudioType(@NonNull int); - method @NonNull public android.service.voice.HotwordTrainingAudio.Builder setHotwordAudio(@NonNull byte...); + method @NonNull public android.service.voice.HotwordTrainingAudio.Builder setHotwordAudio(@NonNull byte[]); method @NonNull public android.service.voice.HotwordTrainingAudio.Builder setHotwordOffsetMillis(int); } diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt index e7c0a912383f..d62bea86bd06 100644 --- a/core/api/system-lint-baseline.txt +++ b/core/api/system-lint-baseline.txt @@ -223,3 +223,3143 @@ SamShouldBeLast: android.view.accessibility.AccessibilityManager#addTouchExplora SAM-compatible parameters (such as parameter 1, "listener", in android.view.accessibility.AccessibilityManager.addTouchExplorationStateChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions SamShouldBeLast: android.webkit.WebChromeClient#onShowFileChooser(android.webkit.WebView, android.webkit.ValueCallback<android.net.Uri[]>, android.webkit.WebChromeClient.FileChooserParams): SAM-compatible parameters (such as parameter 2, "filePathCallback", in android.webkit.WebChromeClient.onShowFileChooser) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions + + +UnflaggedApi: android.Manifest.permission#ACCESS_AMBIENT_CONTEXT_EVENT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT +UnflaggedApi: android.Manifest.permission#ACCESS_AMBIENT_LIGHT_STATS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS +UnflaggedApi: android.Manifest.permission#ACCESS_BROADCAST_RADIO: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_BROADCAST_RADIO +UnflaggedApi: android.Manifest.permission#ACCESS_BROADCAST_RESPONSE_STATS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_BROADCAST_RESPONSE_STATS +UnflaggedApi: android.Manifest.permission#ACCESS_CACHE_FILESYSTEM: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_CACHE_FILESYSTEM +UnflaggedApi: android.Manifest.permission#ACCESS_CONTEXT_HUB: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_CONTEXT_HUB +UnflaggedApi: android.Manifest.permission#ACCESS_DRM_CERTIFICATES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_DRM_CERTIFICATES +UnflaggedApi: android.Manifest.permission#ACCESS_FPS_COUNTER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_FPS_COUNTER +UnflaggedApi: android.Manifest.permission#ACCESS_INSTANT_APPS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_INSTANT_APPS +UnflaggedApi: android.Manifest.permission#ACCESS_LOCUS_ID_USAGE_STATS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_LOCUS_ID_USAGE_STATS +UnflaggedApi: android.Manifest.permission#ACCESS_MOCK_LOCATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_MOCK_LOCATION +UnflaggedApi: android.Manifest.permission#ACCESS_MTP: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_MTP +UnflaggedApi: android.Manifest.permission#ACCESS_NETWORK_CONDITIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_NETWORK_CONDITIONS +UnflaggedApi: android.Manifest.permission#ACCESS_NOTIFICATIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_NOTIFICATIONS +UnflaggedApi: android.Manifest.permission#ACCESS_PDB_STATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_PDB_STATE +UnflaggedApi: android.Manifest.permission#ACCESS_RCS_USER_CAPABILITY_EXCHANGE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE +UnflaggedApi: android.Manifest.permission#ACCESS_SHARED_LIBRARIES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_SHARED_LIBRARIES +UnflaggedApi: android.Manifest.permission#ACCESS_SHORTCUTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_SHORTCUTS +UnflaggedApi: android.Manifest.permission#ACCESS_SMARTSPACE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_SMARTSPACE +UnflaggedApi: android.Manifest.permission#ACCESS_SURFACE_FLINGER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_SURFACE_FLINGER +UnflaggedApi: android.Manifest.permission#ACCESS_TUNED_INFO: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_TUNED_INFO +UnflaggedApi: android.Manifest.permission#ACCESS_TV_DESCRAMBLER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_TV_DESCRAMBLER +UnflaggedApi: android.Manifest.permission#ACCESS_TV_SHARED_FILTER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_TV_SHARED_FILTER +UnflaggedApi: android.Manifest.permission#ACCESS_TV_TUNER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_TV_TUNER +UnflaggedApi: android.Manifest.permission#ACCESS_ULTRASOUND: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_ULTRASOUND +UnflaggedApi: android.Manifest.permission#ACCESS_VIBRATOR_STATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACCESS_VIBRATOR_STATE +UnflaggedApi: android.Manifest.permission#ACTIVITY_EMBEDDING: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ACTIVITY_EMBEDDING +UnflaggedApi: android.Manifest.permission#ADD_ALWAYS_UNLOCKED_DISPLAY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY +UnflaggedApi: android.Manifest.permission#ADD_TRUSTED_DISPLAY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ADD_TRUSTED_DISPLAY +UnflaggedApi: android.Manifest.permission#ADJUST_RUNTIME_PERMISSIONS_POLICY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY +UnflaggedApi: android.Manifest.permission#ALLOCATE_AGGRESSIVE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ALLOCATE_AGGRESSIVE +UnflaggedApi: android.Manifest.permission#ALLOW_ANY_CODEC_FOR_PLAYBACK: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK +UnflaggedApi: android.Manifest.permission#ALLOW_PLACE_IN_MULTI_PANE_SETTINGS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ALLOW_PLACE_IN_MULTI_PANE_SETTINGS +UnflaggedApi: android.Manifest.permission#ALLOW_SLIPPERY_TOUCHES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ALLOW_SLIPPERY_TOUCHES +UnflaggedApi: android.Manifest.permission#ALWAYS_UPDATE_WALLPAPER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ALWAYS_UPDATE_WALLPAPER +UnflaggedApi: android.Manifest.permission#AMBIENT_WALLPAPER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.AMBIENT_WALLPAPER +UnflaggedApi: android.Manifest.permission#APPROVE_INCIDENT_REPORTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.APPROVE_INCIDENT_REPORTS +UnflaggedApi: android.Manifest.permission#ASSOCIATE_COMPANION_DEVICES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ASSOCIATE_COMPANION_DEVICES +UnflaggedApi: android.Manifest.permission#BACKGROUND_CAMERA: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BACKGROUND_CAMERA +UnflaggedApi: android.Manifest.permission#BACKUP: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BACKUP +UnflaggedApi: android.Manifest.permission#BATTERY_PREDICTION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BATTERY_PREDICTION +UnflaggedApi: android.Manifest.permission#BIND_AMBIENT_CONTEXT_DETECTION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_AMBIENT_CONTEXT_DETECTION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_ATTENTION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_ATTENTION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_AUGMENTED_AUTOFILL_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_AUGMENTED_AUTOFILL_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_CALL_DIAGNOSTIC_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_CALL_DIAGNOSTIC_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_CALL_STREAMING_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_CALL_STREAMING_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_CELL_BROADCAST_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_CELL_BROADCAST_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_CONTENT_CAPTURE_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_CONTENT_CAPTURE_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_CONTENT_SUGGESTIONS_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_CONTENT_SUGGESTIONS_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_DIRECTORY_SEARCH: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_DIRECTORY_SEARCH +UnflaggedApi: android.Manifest.permission#BIND_DISPLAY_HASHING_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_DISPLAY_HASHING_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_DOMAIN_VERIFICATION_AGENT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_DOMAIN_VERIFICATION_AGENT +UnflaggedApi: android.Manifest.permission#BIND_EUICC_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_EUICC_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_EXTERNAL_STORAGE_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_EXTERNAL_STORAGE_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_FIELD_CLASSIFICATION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_FIELD_CLASSIFICATION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_GBA_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_GBA_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_HOTWORD_DETECTION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_IMS_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_IMS_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_KEYGUARD_APPWIDGET: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_KEYGUARD_APPWIDGET +UnflaggedApi: android.Manifest.permission#BIND_MUSIC_RECOGNITION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_MUSIC_RECOGNITION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_NETWORK_RECOMMENDATION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_NETWORK_RECOMMENDATION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_NOTIFICATION_ASSISTANT_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_NOTIFICATION_ASSISTANT_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_PHONE_ACCOUNT_SUGGESTION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_PRINT_RECOMMENDATION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_PRINT_RECOMMENDATION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_REMOTE_LOCKSCREEN_VALIDATION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_REMOTE_LOCKSCREEN_VALIDATION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_RESOLVER_RANKER_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_RESOLVER_RANKER_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_RESUME_ON_REBOOT_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_RESUME_ON_REBOOT_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_ROTATION_RESOLVER_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_ROTATION_RESOLVER_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_RUNTIME_PERMISSION_PRESENTER_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_SATELLITE_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_SATELLITE_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_SETTINGS_SUGGESTIONS_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_SETTINGS_SUGGESTIONS_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_SOUND_TRIGGER_DETECTION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_SOUND_TRIGGER_DETECTION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_TELEPHONY_DATA_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_TELEPHONY_DATA_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_TELEPHONY_NETWORK_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_TELEPHONY_NETWORK_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_TEXTCLASSIFIER_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_TEXTCLASSIFIER_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_TIME_ZONE_PROVIDER_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_TIME_ZONE_PROVIDER_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_TRACE_REPORT_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_TRACE_REPORT_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_TRANSLATION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_TRANSLATION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_TRUST_AGENT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_TRUST_AGENT +UnflaggedApi: android.Manifest.permission#BIND_TV_REMOTE_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_TV_REMOTE_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_VISUAL_QUERY_DETECTION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_VISUAL_QUERY_DETECTION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_WALLPAPER_EFFECTS_GENERATION_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_WALLPAPER_EFFECTS_GENERATION_SERVICE +UnflaggedApi: android.Manifest.permission#BIND_WEARABLE_SENSING_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BIND_WEARABLE_SENSING_SERVICE +UnflaggedApi: android.Manifest.permission#BLUETOOTH_MAP: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BLUETOOTH_MAP +UnflaggedApi: android.Manifest.permission#BRICK: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BRICK +UnflaggedApi: android.Manifest.permission#BRIGHTNESS_SLIDER_USAGE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BRIGHTNESS_SLIDER_USAGE +UnflaggedApi: android.Manifest.permission#BROADCAST_CLOSE_SYSTEM_DIALOGS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS +UnflaggedApi: android.Manifest.permission#BYPASS_ROLE_QUALIFICATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.BYPASS_ROLE_QUALIFICATION +UnflaggedApi: android.Manifest.permission#CALL_AUDIO_INTERCEPTION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CALL_AUDIO_INTERCEPTION +UnflaggedApi: android.Manifest.permission#CAMERA_DISABLE_TRANSMIT_LED: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CAMERA_DISABLE_TRANSMIT_LED +UnflaggedApi: android.Manifest.permission#CAMERA_OPEN_CLOSE_LISTENER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CAMERA_OPEN_CLOSE_LISTENER +UnflaggedApi: android.Manifest.permission#CAPTURE_AUDIO_HOTWORD: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CAPTURE_AUDIO_HOTWORD +UnflaggedApi: android.Manifest.permission#CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CAPTURE_CONSENTLESS_BUGREPORT_ON_USERDEBUG_BUILD +UnflaggedApi: android.Manifest.permission#CAPTURE_MEDIA_OUTPUT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CAPTURE_MEDIA_OUTPUT +UnflaggedApi: android.Manifest.permission#CAPTURE_TUNER_AUDIO_INPUT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CAPTURE_TUNER_AUDIO_INPUT +UnflaggedApi: android.Manifest.permission#CAPTURE_TV_INPUT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CAPTURE_TV_INPUT +UnflaggedApi: android.Manifest.permission#CAPTURE_VOICE_COMMUNICATION_OUTPUT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CAPTURE_VOICE_COMMUNICATION_OUTPUT +UnflaggedApi: android.Manifest.permission#CHANGE_APP_IDLE_STATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CHANGE_APP_IDLE_STATE +UnflaggedApi: android.Manifest.permission#CHANGE_APP_LAUNCH_TIME_ESTIMATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CHANGE_APP_LAUNCH_TIME_ESTIMATE +UnflaggedApi: android.Manifest.permission#CHANGE_DEVICE_IDLE_TEMP_WHITELIST: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST +UnflaggedApi: android.Manifest.permission#CHECK_REMOTE_LOCKSCREEN: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CHECK_REMOTE_LOCKSCREEN +UnflaggedApi: android.Manifest.permission#CLEAR_APP_USER_DATA: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CLEAR_APP_USER_DATA +UnflaggedApi: android.Manifest.permission#COMPANION_APPROVE_WIFI_CONNECTIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.COMPANION_APPROVE_WIFI_CONNECTIONS +UnflaggedApi: android.Manifest.permission#CONFIGURE_DISPLAY_BRIGHTNESS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS +UnflaggedApi: android.Manifest.permission#CONFIGURE_INTERACT_ACROSS_PROFILES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CONFIGURE_INTERACT_ACROSS_PROFILES +UnflaggedApi: android.Manifest.permission#CONNECTIVITY_USE_RESTRICTED_NETWORKS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS +UnflaggedApi: android.Manifest.permission#CONTROL_DEVICE_LIGHTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CONTROL_DEVICE_LIGHTS +UnflaggedApi: android.Manifest.permission#CONTROL_DISPLAY_COLOR_TRANSFORMS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS +UnflaggedApi: android.Manifest.permission#CONTROL_DISPLAY_SATURATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CONTROL_DISPLAY_SATURATION +UnflaggedApi: android.Manifest.permission#CONTROL_INCALL_EXPERIENCE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CONTROL_INCALL_EXPERIENCE +UnflaggedApi: android.Manifest.permission#CONTROL_KEYGUARD_SECURE_NOTIFICATIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CONTROL_KEYGUARD_SECURE_NOTIFICATIONS +UnflaggedApi: android.Manifest.permission#CONTROL_OEM_PAID_NETWORK_PREFERENCE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CONTROL_OEM_PAID_NETWORK_PREFERENCE +UnflaggedApi: android.Manifest.permission#CONTROL_VPN: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CONTROL_VPN +UnflaggedApi: android.Manifest.permission#CREATE_USERS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CREATE_USERS +UnflaggedApi: android.Manifest.permission#CREATE_VIRTUAL_DEVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CREATE_VIRTUAL_DEVICE +UnflaggedApi: android.Manifest.permission#CRYPT_KEEPER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.CRYPT_KEEPER +UnflaggedApi: android.Manifest.permission#DEVICE_POWER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.DEVICE_POWER +UnflaggedApi: android.Manifest.permission#DISABLE_SYSTEM_SOUND_EFFECTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.DISABLE_SYSTEM_SOUND_EFFECTS +UnflaggedApi: android.Manifest.permission#DISPATCH_PROVISIONING_MESSAGE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.DISPATCH_PROVISIONING_MESSAGE +UnflaggedApi: android.Manifest.permission#DOMAIN_VERIFICATION_AGENT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.DOMAIN_VERIFICATION_AGENT +UnflaggedApi: android.Manifest.permission#ENTER_CAR_MODE_PRIORITIZED: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ENTER_CAR_MODE_PRIORITIZED +UnflaggedApi: android.Manifest.permission#EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.EXEMPT_FROM_AUDIO_RECORD_RESTRICTIONS +UnflaggedApi: android.Manifest.permission#FORCE_BACK: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.FORCE_BACK +UnflaggedApi: android.Manifest.permission#FORCE_STOP_PACKAGES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.FORCE_STOP_PACKAGES +UnflaggedApi: android.Manifest.permission#GET_APP_METADATA: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.GET_APP_METADATA +UnflaggedApi: android.Manifest.permission#GET_APP_OPS_STATS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.GET_APP_OPS_STATS +UnflaggedApi: android.Manifest.permission#GET_HISTORICAL_APP_OPS_STATS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.GET_HISTORICAL_APP_OPS_STATS +UnflaggedApi: android.Manifest.permission#GET_PROCESS_STATE_AND_OOM_SCORE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.GET_PROCESS_STATE_AND_OOM_SCORE +UnflaggedApi: android.Manifest.permission#GET_RUNTIME_PERMISSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.GET_RUNTIME_PERMISSIONS +UnflaggedApi: android.Manifest.permission#GET_TOP_ACTIVITY_INFO: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.GET_TOP_ACTIVITY_INFO +UnflaggedApi: android.Manifest.permission#GRANT_RUNTIME_PERMISSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS +UnflaggedApi: android.Manifest.permission#GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS_TO_TELEPHONY_DEFAULTS +UnflaggedApi: android.Manifest.permission#HANDLE_CAR_MODE_CHANGES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.HANDLE_CAR_MODE_CHANGES +UnflaggedApi: android.Manifest.permission#HARDWARE_TEST: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.HARDWARE_TEST +UnflaggedApi: android.Manifest.permission#HDMI_CEC: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.HDMI_CEC +UnflaggedApi: android.Manifest.permission#INJECT_EVENTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INJECT_EVENTS +UnflaggedApi: android.Manifest.permission#INSTALL_DPC_PACKAGES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INSTALL_DPC_PACKAGES +UnflaggedApi: android.Manifest.permission#INSTALL_DYNAMIC_SYSTEM: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM +UnflaggedApi: android.Manifest.permission#INSTALL_EXISTING_PACKAGES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INSTALL_EXISTING_PACKAGES +UnflaggedApi: android.Manifest.permission#INSTALL_GRANT_RUNTIME_PERMISSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS +UnflaggedApi: android.Manifest.permission#INSTALL_LOCATION_TIME_ZONE_PROVIDER_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INSTALL_LOCATION_TIME_ZONE_PROVIDER_SERVICE +UnflaggedApi: android.Manifest.permission#INSTALL_PACKAGE_UPDATES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INSTALL_PACKAGE_UPDATES +UnflaggedApi: android.Manifest.permission#INSTALL_SELF_UPDATES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INSTALL_SELF_UPDATES +UnflaggedApi: android.Manifest.permission#INTENT_FILTER_VERIFICATION_AGENT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT +UnflaggedApi: android.Manifest.permission#INTERACT_ACROSS_USERS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INTERACT_ACROSS_USERS +UnflaggedApi: android.Manifest.permission#INTERACT_ACROSS_USERS_FULL: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INTERACT_ACROSS_USERS_FULL +UnflaggedApi: android.Manifest.permission#INTERNAL_SYSTEM_WINDOW: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INTERNAL_SYSTEM_WINDOW +UnflaggedApi: android.Manifest.permission#INVOKE_CARRIER_SETUP: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.INVOKE_CARRIER_SETUP +UnflaggedApi: android.Manifest.permission#KILL_ALL_BACKGROUND_PROCESSES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.KILL_ALL_BACKGROUND_PROCESSES +UnflaggedApi: android.Manifest.permission#KILL_UID: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.KILL_UID +UnflaggedApi: android.Manifest.permission#LAUNCH_DEVICE_MANAGER_SETUP: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.LAUNCH_DEVICE_MANAGER_SETUP +UnflaggedApi: android.Manifest.permission#LAUNCH_PERMISSION_SETTINGS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.LAUNCH_PERMISSION_SETTINGS +UnflaggedApi: android.Manifest.permission#LOCAL_MAC_ADDRESS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.LOCAL_MAC_ADDRESS +UnflaggedApi: android.Manifest.permission#LOCATION_BYPASS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.LOCATION_BYPASS +UnflaggedApi: android.Manifest.permission#LOCK_DEVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.LOCK_DEVICE +UnflaggedApi: android.Manifest.permission#LOG_FOREGROUND_RESOURCE_USE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.LOG_FOREGROUND_RESOURCE_USE +UnflaggedApi: android.Manifest.permission#LOOP_RADIO: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.LOOP_RADIO +UnflaggedApi: android.Manifest.permission#MANAGE_ACCESSIBILITY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_ACCESSIBILITY +UnflaggedApi: android.Manifest.permission#MANAGE_ACTIVITY_TASKS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_ACTIVITY_TASKS +UnflaggedApi: android.Manifest.permission#MANAGE_APP_HIBERNATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_APP_HIBERNATION +UnflaggedApi: android.Manifest.permission#MANAGE_APP_OPS_RESTRICTIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_APP_OPS_RESTRICTIONS +UnflaggedApi: android.Manifest.permission#MANAGE_APP_PREDICTIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_APP_PREDICTIONS +UnflaggedApi: android.Manifest.permission#MANAGE_APP_TOKENS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_APP_TOKENS +UnflaggedApi: android.Manifest.permission#MANAGE_AUTO_FILL: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_AUTO_FILL +UnflaggedApi: android.Manifest.permission#MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_BLUETOOTH_WHEN_WIRELESS_CONSENT_REQUIRED +UnflaggedApi: android.Manifest.permission#MANAGE_CARRIER_OEM_UNLOCK_STATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE +UnflaggedApi: android.Manifest.permission#MANAGE_CA_CERTIFICATES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_CA_CERTIFICATES +UnflaggedApi: android.Manifest.permission#MANAGE_CLIPBOARD_ACCESS_NOTIFICATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_CLIPBOARD_ACCESS_NOTIFICATION +UnflaggedApi: android.Manifest.permission#MANAGE_CLOUDSEARCH: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_CLOUDSEARCH +UnflaggedApi: android.Manifest.permission#MANAGE_CONTENT_CAPTURE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_CONTENT_CAPTURE +UnflaggedApi: android.Manifest.permission#MANAGE_CONTENT_SUGGESTIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_CONTENT_SUGGESTIONS +UnflaggedApi: android.Manifest.permission#MANAGE_DEBUGGING: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_DEBUGGING +UnflaggedApi: android.Manifest.permission#MANAGE_DEFAULT_APPLICATIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_DEFAULT_APPLICATIONS +UnflaggedApi: android.Manifest.permission#MANAGE_DEVICE_ADMINS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_DEVICE_ADMINS +UnflaggedApi: android.Manifest.permission#MANAGE_DEVICE_POLICY_APP_EXEMPTIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_DEVICE_POLICY_APP_EXEMPTIONS +UnflaggedApi: android.Manifest.permission#MANAGE_ETHERNET_NETWORKS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_ETHERNET_NETWORKS +UnflaggedApi: android.Manifest.permission#MANAGE_FACTORY_RESET_PROTECTION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_FACTORY_RESET_PROTECTION +UnflaggedApi: android.Manifest.permission#MANAGE_GAME_ACTIVITY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_GAME_ACTIVITY +UnflaggedApi: android.Manifest.permission#MANAGE_GAME_MODE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_GAME_MODE +UnflaggedApi: android.Manifest.permission#MANAGE_HOTWORD_DETECTION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_HOTWORD_DETECTION +UnflaggedApi: android.Manifest.permission#MANAGE_IPSEC_TUNNELS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_IPSEC_TUNNELS +UnflaggedApi: android.Manifest.permission#MANAGE_LOW_POWER_STANDBY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_LOW_POWER_STANDBY +UnflaggedApi: android.Manifest.permission#MANAGE_MUSIC_RECOGNITION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_MUSIC_RECOGNITION +UnflaggedApi: android.Manifest.permission#MANAGE_NOTIFICATION_LISTENERS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_NOTIFICATION_LISTENERS +UnflaggedApi: android.Manifest.permission#MANAGE_ONE_TIME_PERMISSION_SESSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS +UnflaggedApi: android.Manifest.permission#MANAGE_PROFILE_AND_DEVICE_OWNERS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS +UnflaggedApi: android.Manifest.permission#MANAGE_ROLE_HOLDERS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_ROLE_HOLDERS +UnflaggedApi: android.Manifest.permission#MANAGE_ROLLBACKS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_ROLLBACKS +UnflaggedApi: android.Manifest.permission#MANAGE_ROTATION_RESOLVER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_ROTATION_RESOLVER +UnflaggedApi: android.Manifest.permission#MANAGE_SAFETY_CENTER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_SAFETY_CENTER +UnflaggedApi: android.Manifest.permission#MANAGE_SEARCH_UI: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_SEARCH_UI +UnflaggedApi: android.Manifest.permission#MANAGE_SENSOR_PRIVACY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_SENSOR_PRIVACY +UnflaggedApi: android.Manifest.permission#MANAGE_SMARTSPACE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_SMARTSPACE +UnflaggedApi: android.Manifest.permission#MANAGE_SOUND_TRIGGER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_SOUND_TRIGGER +UnflaggedApi: android.Manifest.permission#MANAGE_SPEECH_RECOGNITION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_SPEECH_RECOGNITION +UnflaggedApi: android.Manifest.permission#MANAGE_SUBSCRIPTION_PLANS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS +UnflaggedApi: android.Manifest.permission#MANAGE_SUBSCRIPTION_USER_ASSOCIATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION +UnflaggedApi: android.Manifest.permission#MANAGE_TEST_NETWORKS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_TEST_NETWORKS +UnflaggedApi: android.Manifest.permission#MANAGE_TIME_AND_ZONE_DETECTION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_TIME_AND_ZONE_DETECTION +UnflaggedApi: android.Manifest.permission#MANAGE_UI_TRANSLATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_UI_TRANSLATION +UnflaggedApi: android.Manifest.permission#MANAGE_USB: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_USB +UnflaggedApi: android.Manifest.permission#MANAGE_USERS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_USERS +UnflaggedApi: android.Manifest.permission#MANAGE_USER_OEM_UNLOCK_STATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE +UnflaggedApi: android.Manifest.permission#MANAGE_WALLPAPER_EFFECTS_GENERATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_WALLPAPER_EFFECTS_GENERATION +UnflaggedApi: android.Manifest.permission#MANAGE_WEAK_ESCROW_TOKEN: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_WEAK_ESCROW_TOKEN +UnflaggedApi: android.Manifest.permission#MANAGE_WEARABLE_SENSING_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_WEARABLE_SENSING_SERVICE +UnflaggedApi: android.Manifest.permission#MANAGE_WIFI_COUNTRY_CODE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MANAGE_WIFI_COUNTRY_CODE +UnflaggedApi: android.Manifest.permission#MARK_DEVICE_ORGANIZATION_OWNED: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MARK_DEVICE_ORGANIZATION_OWNED +UnflaggedApi: android.Manifest.permission#MEDIA_RESOURCE_OVERRIDE_PID: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MEDIA_RESOURCE_OVERRIDE_PID +UnflaggedApi: android.Manifest.permission#MIGRATE_HEALTH_CONNECT_DATA: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MIGRATE_HEALTH_CONNECT_DATA +UnflaggedApi: android.Manifest.permission#MODIFY_APPWIDGET_BIND_PERMISSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MODIFY_APPWIDGET_BIND_PERMISSIONS +UnflaggedApi: android.Manifest.permission#MODIFY_AUDIO_ROUTING: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MODIFY_AUDIO_ROUTING +UnflaggedApi: android.Manifest.permission#MODIFY_AUDIO_SETTINGS_PRIVILEGED: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MODIFY_AUDIO_SETTINGS_PRIVILEGED +UnflaggedApi: android.Manifest.permission#MODIFY_CELL_BROADCASTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MODIFY_CELL_BROADCASTS +UnflaggedApi: android.Manifest.permission#MODIFY_DAY_NIGHT_MODE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MODIFY_DAY_NIGHT_MODE +UnflaggedApi: android.Manifest.permission#MODIFY_PARENTAL_CONTROLS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MODIFY_PARENTAL_CONTROLS +UnflaggedApi: android.Manifest.permission#MODIFY_QUIET_MODE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MODIFY_QUIET_MODE +UnflaggedApi: android.Manifest.permission#MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE +UnflaggedApi: android.Manifest.permission#MONITOR_DEVICE_CONFIG_ACCESS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS +UnflaggedApi: android.Manifest.permission#MOVE_PACKAGE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.MOVE_PACKAGE +UnflaggedApi: android.Manifest.permission#NETWORK_AIRPLANE_MODE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NETWORK_AIRPLANE_MODE +UnflaggedApi: android.Manifest.permission#NETWORK_CARRIER_PROVISIONING: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NETWORK_CARRIER_PROVISIONING +UnflaggedApi: android.Manifest.permission#NETWORK_FACTORY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NETWORK_FACTORY +UnflaggedApi: android.Manifest.permission#NETWORK_MANAGED_PROVISIONING: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NETWORK_MANAGED_PROVISIONING +UnflaggedApi: android.Manifest.permission#NETWORK_SCAN: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NETWORK_SCAN +UnflaggedApi: android.Manifest.permission#NETWORK_SETTINGS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NETWORK_SETTINGS +UnflaggedApi: android.Manifest.permission#NETWORK_SETUP_WIZARD: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NETWORK_SETUP_WIZARD +UnflaggedApi: android.Manifest.permission#NETWORK_SIGNAL_STRENGTH_WAKEUP: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP +UnflaggedApi: android.Manifest.permission#NETWORK_STACK: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NETWORK_STACK +UnflaggedApi: android.Manifest.permission#NETWORK_STATS_PROVIDER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NETWORK_STATS_PROVIDER +UnflaggedApi: android.Manifest.permission#NFC_SET_CONTROLLER_ALWAYS_ON: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NFC_SET_CONTROLLER_ALWAYS_ON +UnflaggedApi: android.Manifest.permission#NOTIFICATION_DURING_SETUP: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NOTIFICATION_DURING_SETUP +UnflaggedApi: android.Manifest.permission#NOTIFY_TV_INPUTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.NOTIFY_TV_INPUTS +UnflaggedApi: android.Manifest.permission#OBSERVE_APP_USAGE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.OBSERVE_APP_USAGE +UnflaggedApi: android.Manifest.permission#OBSERVE_NETWORK_POLICY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.OBSERVE_NETWORK_POLICY +UnflaggedApi: android.Manifest.permission#OBSERVE_ROLE_HOLDERS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.OBSERVE_ROLE_HOLDERS +UnflaggedApi: android.Manifest.permission#OBSERVE_SENSOR_PRIVACY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.OBSERVE_SENSOR_PRIVACY +UnflaggedApi: android.Manifest.permission#OPEN_ACCESSIBILITY_DETAILS_SETTINGS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.OPEN_ACCESSIBILITY_DETAILS_SETTINGS +UnflaggedApi: android.Manifest.permission#OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD +UnflaggedApi: android.Manifest.permission#PACKAGE_VERIFICATION_AGENT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.PACKAGE_VERIFICATION_AGENT +UnflaggedApi: android.Manifest.permission#PACKET_KEEPALIVE_OFFLOAD: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD +UnflaggedApi: android.Manifest.permission#PEERS_MAC_ADDRESS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.PEERS_MAC_ADDRESS +UnflaggedApi: android.Manifest.permission#PERFORM_CDMA_PROVISIONING: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.PERFORM_CDMA_PROVISIONING +UnflaggedApi: android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION +UnflaggedApi: android.Manifest.permission#PERFORM_SIM_ACTIVATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.PERFORM_SIM_ACTIVATION +UnflaggedApi: android.Manifest.permission#POWER_SAVER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.POWER_SAVER +UnflaggedApi: android.Manifest.permission#PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE +UnflaggedApi: android.Manifest.permission#PROVIDE_RESOLVER_RANKER_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.PROVIDE_RESOLVER_RANKER_SERVICE +UnflaggedApi: android.Manifest.permission#PROVIDE_TRUST_AGENT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.PROVIDE_TRUST_AGENT +UnflaggedApi: android.Manifest.permission#PROVISION_DEMO_DEVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.PROVISION_DEMO_DEVICE +UnflaggedApi: android.Manifest.permission#QUERY_ADMIN_POLICY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.QUERY_ADMIN_POLICY +UnflaggedApi: android.Manifest.permission#QUERY_CLONED_APPS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.QUERY_CLONED_APPS +UnflaggedApi: android.Manifest.permission#QUERY_USERS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.QUERY_USERS +UnflaggedApi: android.Manifest.permission#RADIO_SCAN_WITHOUT_LOCATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RADIO_SCAN_WITHOUT_LOCATION +UnflaggedApi: android.Manifest.permission#READ_ACTIVE_EMERGENCY_SESSION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_ACTIVE_EMERGENCY_SESSION +UnflaggedApi: android.Manifest.permission#READ_APP_SPECIFIC_LOCALES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_APP_SPECIFIC_LOCALES +UnflaggedApi: android.Manifest.permission#READ_CARRIER_APP_INFO: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_CARRIER_APP_INFO +UnflaggedApi: android.Manifest.permission#READ_CELL_BROADCASTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_CELL_BROADCASTS +UnflaggedApi: android.Manifest.permission#READ_CLIPBOARD_IN_BACKGROUND: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_CLIPBOARD_IN_BACKGROUND +UnflaggedApi: android.Manifest.permission#READ_CONTENT_RATING_SYSTEMS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_CONTENT_RATING_SYSTEMS +UnflaggedApi: android.Manifest.permission#READ_DEVICE_CONFIG: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_DEVICE_CONFIG +UnflaggedApi: android.Manifest.permission#READ_DREAM_STATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_DREAM_STATE +UnflaggedApi: android.Manifest.permission#READ_GLOBAL_APP_SEARCH_DATA: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_GLOBAL_APP_SEARCH_DATA +UnflaggedApi: android.Manifest.permission#READ_INSTALLED_SESSION_PATHS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_INSTALLED_SESSION_PATHS +UnflaggedApi: android.Manifest.permission#READ_INSTALL_SESSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_INSTALL_SESSIONS +UnflaggedApi: android.Manifest.permission#READ_NETWORK_USAGE_HISTORY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_NETWORK_USAGE_HISTORY +UnflaggedApi: android.Manifest.permission#READ_OEM_UNLOCK_STATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_OEM_UNLOCK_STATE +UnflaggedApi: android.Manifest.permission#READ_PEOPLE_DATA: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_PEOPLE_DATA +UnflaggedApi: android.Manifest.permission#READ_PRINT_SERVICES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_PRINT_SERVICES +UnflaggedApi: android.Manifest.permission#READ_PRINT_SERVICE_RECOMMENDATIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_PRINT_SERVICE_RECOMMENDATIONS +UnflaggedApi: android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE +UnflaggedApi: android.Manifest.permission#READ_PROJECTION_STATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_PROJECTION_STATE +UnflaggedApi: android.Manifest.permission#READ_RESTRICTED_STATS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_RESTRICTED_STATS +UnflaggedApi: android.Manifest.permission#READ_RUNTIME_PROFILES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_RUNTIME_PROFILES +UnflaggedApi: android.Manifest.permission#READ_SAFETY_CENTER_STATUS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_SAFETY_CENTER_STATUS +UnflaggedApi: android.Manifest.permission#READ_SEARCH_INDEXABLES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_SEARCH_INDEXABLES +UnflaggedApi: android.Manifest.permission#READ_SYSTEM_UPDATE_INFO: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_SYSTEM_UPDATE_INFO +UnflaggedApi: android.Manifest.permission#READ_WALLPAPER_INTERNAL: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_WALLPAPER_INTERNAL +UnflaggedApi: android.Manifest.permission#READ_WIFI_CREDENTIAL: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_WIFI_CREDENTIAL +UnflaggedApi: android.Manifest.permission#READ_WRITE_SYNC_DISABLED_MODE_CONFIG: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.READ_WRITE_SYNC_DISABLED_MODE_CONFIG +UnflaggedApi: android.Manifest.permission#REAL_GET_TASKS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REAL_GET_TASKS +UnflaggedApi: android.Manifest.permission#RECEIVE_BLUETOOTH_MAP: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RECEIVE_BLUETOOTH_MAP +UnflaggedApi: android.Manifest.permission#RECEIVE_DATA_ACTIVITY_CHANGE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE +UnflaggedApi: android.Manifest.permission#RECEIVE_DEVICE_CUSTOMIZATION_READY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RECEIVE_DEVICE_CUSTOMIZATION_READY +UnflaggedApi: android.Manifest.permission#RECEIVE_EMERGENCY_BROADCAST: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RECEIVE_EMERGENCY_BROADCAST +UnflaggedApi: android.Manifest.permission#RECEIVE_WIFI_CREDENTIAL_CHANGE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RECEIVE_WIFI_CREDENTIAL_CHANGE +UnflaggedApi: android.Manifest.permission#RECORD_BACKGROUND_AUDIO: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RECORD_BACKGROUND_AUDIO +UnflaggedApi: android.Manifest.permission#RECOVERY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RECOVERY +UnflaggedApi: android.Manifest.permission#RECOVER_KEYSTORE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RECOVER_KEYSTORE +UnflaggedApi: android.Manifest.permission#REGISTER_CALL_PROVIDER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REGISTER_CALL_PROVIDER +UnflaggedApi: android.Manifest.permission#REGISTER_CONNECTION_MANAGER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REGISTER_CONNECTION_MANAGER +UnflaggedApi: android.Manifest.permission#REGISTER_NSD_OFFLOAD_ENGINE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REGISTER_NSD_OFFLOAD_ENGINE +UnflaggedApi: android.Manifest.permission#REGISTER_SIM_SUBSCRIPTION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REGISTER_SIM_SUBSCRIPTION +UnflaggedApi: android.Manifest.permission#REGISTER_STATS_PULL_ATOM: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REGISTER_STATS_PULL_ATOM +UnflaggedApi: android.Manifest.permission#REMOTE_DISPLAY_PROVIDER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REMOTE_DISPLAY_PROVIDER +UnflaggedApi: android.Manifest.permission#REMOVE_DRM_CERTIFICATES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REMOVE_DRM_CERTIFICATES +UnflaggedApi: android.Manifest.permission#REMOVE_TASKS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REMOVE_TASKS +UnflaggedApi: android.Manifest.permission#RENOUNCE_PERMISSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RENOUNCE_PERMISSIONS +UnflaggedApi: android.Manifest.permission#REPORT_USAGE_STATS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REPORT_USAGE_STATS +UnflaggedApi: android.Manifest.permission#REQUEST_NOTIFICATION_ASSISTANT_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE +UnflaggedApi: android.Manifest.permission#RESET_PASSWORD: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RESET_PASSWORD +UnflaggedApi: android.Manifest.permission#RESTART_WIFI_SUBSYSTEM: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RESTART_WIFI_SUBSYSTEM +UnflaggedApi: android.Manifest.permission#RESTORE_RUNTIME_PERMISSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RESTORE_RUNTIME_PERMISSIONS +UnflaggedApi: android.Manifest.permission#RESTRICTED_VR_ACCESS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RESTRICTED_VR_ACCESS +UnflaggedApi: android.Manifest.permission#RETRIEVE_WINDOW_CONTENT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.RETRIEVE_WINDOW_CONTENT +UnflaggedApi: android.Manifest.permission#REVIEW_ACCESSIBILITY_SERVICES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REVIEW_ACCESSIBILITY_SERVICES +UnflaggedApi: android.Manifest.permission#REVOKE_RUNTIME_PERMISSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS +UnflaggedApi: android.Manifest.permission#ROTATE_SURFACE_FLINGER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.ROTATE_SURFACE_FLINGER +UnflaggedApi: android.Manifest.permission#SATELLITE_COMMUNICATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SATELLITE_COMMUNICATION +UnflaggedApi: android.Manifest.permission#SCHEDULE_PRIORITIZED_ALARM: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SCHEDULE_PRIORITIZED_ALARM +UnflaggedApi: android.Manifest.permission#SECURE_ELEMENT_PRIVILEGED_OPERATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SECURE_ELEMENT_PRIVILEGED_OPERATION +UnflaggedApi: android.Manifest.permission#SEND_CATEGORY_CAR_NOTIFICATIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SEND_CATEGORY_CAR_NOTIFICATIONS +UnflaggedApi: android.Manifest.permission#SEND_DEVICE_CUSTOMIZATION_READY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SEND_DEVICE_CUSTOMIZATION_READY +UnflaggedApi: android.Manifest.permission#SEND_SAFETY_CENTER_UPDATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SEND_SAFETY_CENTER_UPDATE +UnflaggedApi: android.Manifest.permission#SEND_SHOW_SUSPENDED_APP_DETAILS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SEND_SHOW_SUSPENDED_APP_DETAILS +UnflaggedApi: android.Manifest.permission#SEND_SMS_NO_CONFIRMATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SEND_SMS_NO_CONFIRMATION +UnflaggedApi: android.Manifest.permission#SERIAL_PORT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SERIAL_PORT +UnflaggedApi: android.Manifest.permission#SET_ACTIVITY_WATCHER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_ACTIVITY_WATCHER +UnflaggedApi: android.Manifest.permission#SET_CLIP_SOURCE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_CLIP_SOURCE +UnflaggedApi: android.Manifest.permission#SET_DEFAULT_ACCOUNT_FOR_CONTACTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_DEFAULT_ACCOUNT_FOR_CONTACTS +UnflaggedApi: android.Manifest.permission#SET_HARMFUL_APP_WARNINGS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_HARMFUL_APP_WARNINGS +UnflaggedApi: android.Manifest.permission#SET_LOW_POWER_STANDBY_PORTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_LOW_POWER_STANDBY_PORTS +UnflaggedApi: android.Manifest.permission#SET_MEDIA_KEY_LISTENER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_MEDIA_KEY_LISTENER +UnflaggedApi: android.Manifest.permission#SET_ORIENTATION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_ORIENTATION +UnflaggedApi: android.Manifest.permission#SET_POINTER_SPEED: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_POINTER_SPEED +UnflaggedApi: android.Manifest.permission#SET_SCREEN_COMPATIBILITY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_SCREEN_COMPATIBILITY +UnflaggedApi: android.Manifest.permission#SET_SYSTEM_AUDIO_CAPTION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_SYSTEM_AUDIO_CAPTION +UnflaggedApi: android.Manifest.permission#SET_UNRESTRICTED_KEEP_CLEAR_AREAS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS +UnflaggedApi: android.Manifest.permission#SET_VOLUME_KEY_LONG_PRESS_LISTENER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER +UnflaggedApi: android.Manifest.permission#SET_WALLPAPER_COMPONENT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_WALLPAPER_COMPONENT +UnflaggedApi: android.Manifest.permission#SET_WALLPAPER_DIM_AMOUNT: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SET_WALLPAPER_DIM_AMOUNT +UnflaggedApi: android.Manifest.permission#SHOW_KEYGUARD_MESSAGE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SHOW_KEYGUARD_MESSAGE +UnflaggedApi: android.Manifest.permission#SHUTDOWN: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SHUTDOWN +UnflaggedApi: android.Manifest.permission#SIGNAL_REBOOT_READINESS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SIGNAL_REBOOT_READINESS +UnflaggedApi: android.Manifest.permission#SOUND_TRIGGER_RUN_IN_BATTERY_SAVER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SOUND_TRIGGER_RUN_IN_BATTERY_SAVER +UnflaggedApi: android.Manifest.permission#STAGE_HEALTH_CONNECT_REMOTE_DATA: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.STAGE_HEALTH_CONNECT_REMOTE_DATA +UnflaggedApi: android.Manifest.permission#START_ACTIVITIES_FROM_BACKGROUND: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.START_ACTIVITIES_FROM_BACKGROUND +UnflaggedApi: android.Manifest.permission#START_CROSS_PROFILE_ACTIVITIES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.START_CROSS_PROFILE_ACTIVITIES +UnflaggedApi: android.Manifest.permission#START_REVIEW_PERMISSION_DECISIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.START_REVIEW_PERMISSION_DECISIONS +UnflaggedApi: android.Manifest.permission#START_TASKS_FROM_RECENTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.START_TASKS_FROM_RECENTS +UnflaggedApi: android.Manifest.permission#STATUS_BAR_SERVICE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.STATUS_BAR_SERVICE +UnflaggedApi: android.Manifest.permission#STOP_APP_SWITCHES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.STOP_APP_SWITCHES +UnflaggedApi: android.Manifest.permission#SUBSTITUTE_NOTIFICATION_APP_NAME: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME +UnflaggedApi: android.Manifest.permission#SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SUBSTITUTE_SHARE_TARGET_APP_NAME_AND_ICON +UnflaggedApi: android.Manifest.permission#SUGGEST_EXTERNAL_TIME: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SUGGEST_EXTERNAL_TIME +UnflaggedApi: android.Manifest.permission#SUSPEND_APPS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SUSPEND_APPS +UnflaggedApi: android.Manifest.permission#SYSTEM_APPLICATION_OVERLAY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY +UnflaggedApi: android.Manifest.permission#SYSTEM_CAMERA: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.SYSTEM_CAMERA +UnflaggedApi: android.Manifest.permission#TETHER_PRIVILEGED: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.TETHER_PRIVILEGED +UnflaggedApi: android.Manifest.permission#TIS_EXTENSION_INTERFACE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.TIS_EXTENSION_INTERFACE +UnflaggedApi: android.Manifest.permission#TOGGLE_AUTOMOTIVE_PROJECTION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.TOGGLE_AUTOMOTIVE_PROJECTION +UnflaggedApi: android.Manifest.permission#TRIGGER_LOST_MODE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.TRIGGER_LOST_MODE +UnflaggedApi: android.Manifest.permission#TV_INPUT_HARDWARE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.TV_INPUT_HARDWARE +UnflaggedApi: android.Manifest.permission#TV_VIRTUAL_REMOTE_CONTROLLER: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.TV_VIRTUAL_REMOTE_CONTROLLER +UnflaggedApi: android.Manifest.permission#UNLIMITED_SHORTCUTS_API_CALLS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.UNLIMITED_SHORTCUTS_API_CALLS +UnflaggedApi: android.Manifest.permission#UPDATE_APP_OPS_STATS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.UPDATE_APP_OPS_STATS +UnflaggedApi: android.Manifest.permission#UPDATE_DEVICE_MANAGEMENT_RESOURCES: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.UPDATE_DEVICE_MANAGEMENT_RESOURCES +UnflaggedApi: android.Manifest.permission#UPDATE_DOMAIN_VERIFICATION_USER_SELECTION: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.UPDATE_DOMAIN_VERIFICATION_USER_SELECTION +UnflaggedApi: android.Manifest.permission#UPDATE_FONTS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.UPDATE_FONTS +UnflaggedApi: android.Manifest.permission#UPDATE_LOCK: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.UPDATE_LOCK +UnflaggedApi: android.Manifest.permission#UPGRADE_RUNTIME_PERMISSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.UPGRADE_RUNTIME_PERMISSIONS +UnflaggedApi: android.Manifest.permission#USER_ACTIVITY: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.USER_ACTIVITY +UnflaggedApi: android.Manifest.permission#USE_COLORIZED_NOTIFICATIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS +UnflaggedApi: android.Manifest.permission#USE_RESERVED_DISK: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.USE_RESERVED_DISK +UnflaggedApi: android.Manifest.permission#UWB_PRIVILEGED: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.UWB_PRIVILEGED +UnflaggedApi: android.Manifest.permission#WHITELIST_AUTO_REVOKE_PERMISSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS +UnflaggedApi: android.Manifest.permission#WHITELIST_RESTRICTED_PERMISSIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS +UnflaggedApi: android.Manifest.permission#WIFI_ACCESS_COEX_UNSAFE_CHANNELS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WIFI_ACCESS_COEX_UNSAFE_CHANNELS +UnflaggedApi: android.Manifest.permission#WIFI_SET_DEVICE_MOBILITY_STATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE +UnflaggedApi: android.Manifest.permission#WIFI_UPDATE_COEX_UNSAFE_CHANNELS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WIFI_UPDATE_COEX_UNSAFE_CHANNELS +UnflaggedApi: android.Manifest.permission#WIFI_UPDATE_USABILITY_STATS_SCORE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE +UnflaggedApi: android.Manifest.permission#WRITE_ALLOWLISTED_DEVICE_CONFIG: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG +UnflaggedApi: android.Manifest.permission#WRITE_DEVICE_CONFIG: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WRITE_DEVICE_CONFIG +UnflaggedApi: android.Manifest.permission#WRITE_DREAM_STATE: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WRITE_DREAM_STATE +UnflaggedApi: android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS +UnflaggedApi: android.Manifest.permission#WRITE_OBB: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WRITE_OBB +UnflaggedApi: android.Manifest.permission#WRITE_SECURITY_LOG: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WRITE_SECURITY_LOG +UnflaggedApi: android.Manifest.permission#WRITE_SMS: + New API must be flagged with @FlaggedApi: field android.Manifest.permission.WRITE_SMS +UnflaggedApi: android.Manifest.permission_group#UNDEFINED: + New API must be flagged with @FlaggedApi: field android.Manifest.permission_group.UNDEFINED +UnflaggedApi: android.R.array#config_keySystemUuidMapping: + New API must be flagged with @FlaggedApi: field android.R.array.config_keySystemUuidMapping +UnflaggedApi: android.R.array#config_optionalIpSecAlgorithms: + New API must be flagged with @FlaggedApi: field android.R.array.config_optionalIpSecAlgorithms +UnflaggedApi: android.R.attr#allowClearUserDataOnFailedRestore: + New API must be flagged with @FlaggedApi: field android.R.attr.allowClearUserDataOnFailedRestore +UnflaggedApi: android.R.attr#gameSessionService: + New API must be flagged with @FlaggedApi: field android.R.attr.gameSessionService +UnflaggedApi: android.R.attr#hotwordDetectionService: + New API must be flagged with @FlaggedApi: field android.R.attr.hotwordDetectionService +UnflaggedApi: android.R.attr#isVrOnly: + New API must be flagged with @FlaggedApi: field android.R.attr.isVrOnly +UnflaggedApi: android.R.attr#minExtensionVersion: + New API must be flagged with @FlaggedApi: field android.R.attr.minExtensionVersion +UnflaggedApi: android.R.attr#playHomeTransitionSound: + New API must be flagged with @FlaggedApi: field android.R.attr.playHomeTransitionSound +UnflaggedApi: android.R.attr#requiredSystemPropertyName: + New API must be flagged with @FlaggedApi: field android.R.attr.requiredSystemPropertyName +UnflaggedApi: android.R.attr#requiredSystemPropertyValue: + New API must be flagged with @FlaggedApi: field android.R.attr.requiredSystemPropertyValue +UnflaggedApi: android.R.attr#sdkVersion: + New API must be flagged with @FlaggedApi: field android.R.attr.sdkVersion +UnflaggedApi: android.R.attr#supportsAmbientMode: + New API must be flagged with @FlaggedApi: field android.R.attr.supportsAmbientMode +UnflaggedApi: android.R.attr#userRestriction: + New API must be flagged with @FlaggedApi: field android.R.attr.userRestriction +UnflaggedApi: android.R.attr#visualQueryDetectionService: + New API must be flagged with @FlaggedApi: field android.R.attr.visualQueryDetectionService +UnflaggedApi: android.R.bool#config_enableDefaultNotes: + New API must be flagged with @FlaggedApi: field android.R.bool.config_enableDefaultNotes +UnflaggedApi: android.R.bool#config_enableDefaultNotesForWorkProfile: + New API must be flagged with @FlaggedApi: field android.R.bool.config_enableDefaultNotesForWorkProfile +UnflaggedApi: android.R.bool#config_enableQrCodeScannerOnLockScreen: + New API must be flagged with @FlaggedApi: field android.R.bool.config_enableQrCodeScannerOnLockScreen +UnflaggedApi: android.R.bool#config_safetyProtectionEnabled: + New API must be flagged with @FlaggedApi: field android.R.bool.config_safetyProtectionEnabled +UnflaggedApi: android.R.bool#config_sendPackageName: + New API must be flagged with @FlaggedApi: field android.R.bool.config_sendPackageName +UnflaggedApi: android.R.bool#config_showDefaultAssistant: + New API must be flagged with @FlaggedApi: field android.R.bool.config_showDefaultAssistant +UnflaggedApi: android.R.bool#config_showDefaultEmergency: + New API must be flagged with @FlaggedApi: field android.R.bool.config_showDefaultEmergency +UnflaggedApi: android.R.bool#config_showDefaultHome: + New API must be flagged with @FlaggedApi: field android.R.bool.config_showDefaultHome +UnflaggedApi: android.R.color#system_notification_accent_color: + New API must be flagged with @FlaggedApi: field android.R.color.system_notification_accent_color +UnflaggedApi: android.R.dimen#config_restrictedIconSize: + New API must be flagged with @FlaggedApi: field android.R.dimen.config_restrictedIconSize +UnflaggedApi: android.R.dimen#config_viewConfigurationHandwritingGestureLineMargin: + New API must be flagged with @FlaggedApi: field android.R.dimen.config_viewConfigurationHandwritingGestureLineMargin +UnflaggedApi: android.R.drawable#ic_info: + New API must be flagged with @FlaggedApi: field android.R.drawable.ic_info +UnflaggedApi: android.R.drawable#ic_safety_protection: + New API must be flagged with @FlaggedApi: field android.R.drawable.ic_safety_protection +UnflaggedApi: android.R.raw#loaderror: + New API must be flagged with @FlaggedApi: field android.R.raw.loaderror +UnflaggedApi: android.R.raw#nodomain: + New API must be flagged with @FlaggedApi: field android.R.raw.nodomain +UnflaggedApi: android.R.string#config_customMediaKeyDispatcher: + New API must be flagged with @FlaggedApi: field android.R.string.config_customMediaKeyDispatcher +UnflaggedApi: android.R.string#config_customMediaSessionPolicyProvider: + New API must be flagged with @FlaggedApi: field android.R.string.config_customMediaSessionPolicyProvider +UnflaggedApi: android.R.string#config_defaultAssistant: + New API must be flagged with @FlaggedApi: field android.R.string.config_defaultAssistant +UnflaggedApi: android.R.string#config_defaultAutomotiveNavigation: + New API must be flagged with @FlaggedApi: field android.R.string.config_defaultAutomotiveNavigation +UnflaggedApi: android.R.string#config_defaultBrowser: + New API must be flagged with @FlaggedApi: field android.R.string.config_defaultBrowser +UnflaggedApi: android.R.string#config_defaultCallRedirection: + New API must be flagged with @FlaggedApi: field android.R.string.config_defaultCallRedirection +UnflaggedApi: android.R.string#config_defaultCallScreening: + New API must be flagged with @FlaggedApi: field android.R.string.config_defaultCallScreening +UnflaggedApi: android.R.string#config_defaultDialer: + New API must be flagged with @FlaggedApi: field android.R.string.config_defaultDialer +UnflaggedApi: android.R.string#config_defaultNotes: + New API must be flagged with @FlaggedApi: field android.R.string.config_defaultNotes +UnflaggedApi: android.R.string#config_defaultRetailDemo: + New API must be flagged with @FlaggedApi: field android.R.string.config_defaultRetailDemo +UnflaggedApi: android.R.string#config_defaultSms: + New API must be flagged with @FlaggedApi: field android.R.string.config_defaultSms +UnflaggedApi: android.R.string#config_devicePolicyManagement: + New API must be flagged with @FlaggedApi: field android.R.string.config_devicePolicyManagement +UnflaggedApi: android.R.string#config_feedbackIntentExtraKey: + New API must be flagged with @FlaggedApi: field android.R.string.config_feedbackIntentExtraKey +UnflaggedApi: android.R.string#config_feedbackIntentNameKey: + New API must be flagged with @FlaggedApi: field android.R.string.config_feedbackIntentNameKey +UnflaggedApi: android.R.string#config_helpIntentExtraKey: + New API must be flagged with @FlaggedApi: field android.R.string.config_helpIntentExtraKey +UnflaggedApi: android.R.string#config_helpIntentNameKey: + New API must be flagged with @FlaggedApi: field android.R.string.config_helpIntentNameKey +UnflaggedApi: android.R.string#config_helpPackageNameKey: + New API must be flagged with @FlaggedApi: field android.R.string.config_helpPackageNameKey +UnflaggedApi: android.R.string#config_helpPackageNameValue: + New API must be flagged with @FlaggedApi: field android.R.string.config_helpPackageNameValue +UnflaggedApi: android.R.string#config_systemActivityRecognizer: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemActivityRecognizer +UnflaggedApi: android.R.string#config_systemAmbientAudioIntelligence: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemAmbientAudioIntelligence +UnflaggedApi: android.R.string#config_systemAppProtectionService: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemAppProtectionService +UnflaggedApi: android.R.string#config_systemAudioIntelligence: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemAudioIntelligence +UnflaggedApi: android.R.string#config_systemAutomotiveCalendarSyncManager: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemAutomotiveCalendarSyncManager +UnflaggedApi: android.R.string#config_systemAutomotiveCluster: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemAutomotiveCluster +UnflaggedApi: android.R.string#config_systemAutomotiveProjection: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemAutomotiveProjection +UnflaggedApi: android.R.string#config_systemCallStreaming: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemCallStreaming +UnflaggedApi: android.R.string#config_systemCompanionDeviceProvider: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemCompanionDeviceProvider +UnflaggedApi: android.R.string#config_systemContacts: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemContacts +UnflaggedApi: android.R.string#config_systemFinancedDeviceController: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemFinancedDeviceController +UnflaggedApi: android.R.string#config_systemGallery: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemGallery +UnflaggedApi: android.R.string#config_systemNotificationIntelligence: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemNotificationIntelligence +UnflaggedApi: android.R.string#config_systemSettingsIntelligence: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemSettingsIntelligence +UnflaggedApi: android.R.string#config_systemShell: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemShell +UnflaggedApi: android.R.string#config_systemSpeechRecognizer: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemSpeechRecognizer +UnflaggedApi: android.R.string#config_systemSupervision: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemSupervision +UnflaggedApi: android.R.string#config_systemTelevisionNotificationHandler: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemTelevisionNotificationHandler +UnflaggedApi: android.R.string#config_systemTextIntelligence: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemTextIntelligence +UnflaggedApi: android.R.string#config_systemUi: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemUi +UnflaggedApi: android.R.string#config_systemUiIntelligence: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemUiIntelligence +UnflaggedApi: android.R.string#config_systemVisualIntelligence: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemVisualIntelligence +UnflaggedApi: android.R.string#config_systemWearHealthService: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemWearHealthService +UnflaggedApi: android.R.string#config_systemWellbeing: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemWellbeing +UnflaggedApi: android.R.string#config_systemWifiCoexManager: + New API must be flagged with @FlaggedApi: field android.R.string.config_systemWifiCoexManager +UnflaggedApi: android.R.string#safety_protection_display_text: + New API must be flagged with @FlaggedApi: field android.R.string.safety_protection_display_text +UnflaggedApi: android.R.style#Theme_DeviceDefault_DocumentsUI: + New API must be flagged with @FlaggedApi: field android.R.style.Theme_DeviceDefault_DocumentsUI +UnflaggedApi: android.R.style#Theme_Leanback_FormWizard: + New API must be flagged with @FlaggedApi: field android.R.style.Theme_Leanback_FormWizard +UnflaggedApi: android.app.ActivityManager#getExternalHistoricalProcessStartReasons(String, int): + New API must be flagged with @FlaggedApi: method android.app.ActivityManager.getExternalHistoricalProcessStartReasons(String,int) +UnflaggedApi: android.app.AppOpsManager#OPSTR_RECEIVE_SANDBOX_TRIGGER_AUDIO: + New API must be flagged with @FlaggedApi: field android.app.AppOpsManager.OPSTR_RECEIVE_SANDBOX_TRIGGER_AUDIO +UnflaggedApi: android.app.AppOpsManager.AttributedHistoricalOps#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.AppOpsManager.AttributedHistoricalOps.equals(Object) +UnflaggedApi: android.app.AppOpsManager.AttributedHistoricalOps#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.AppOpsManager.AttributedHistoricalOps.hashCode() +UnflaggedApi: android.app.AppOpsManager.HistoricalOp#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.AppOpsManager.HistoricalOp.equals(Object) +UnflaggedApi: android.app.AppOpsManager.HistoricalOp#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.AppOpsManager.HistoricalOp.hashCode() +UnflaggedApi: android.app.AppOpsManager.HistoricalOps#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.AppOpsManager.HistoricalOps.equals(Object) +UnflaggedApi: android.app.AppOpsManager.HistoricalOps#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.AppOpsManager.HistoricalOps.hashCode() +UnflaggedApi: android.app.AppOpsManager.HistoricalOps#toString(): + New API must be flagged with @FlaggedApi: method android.app.AppOpsManager.HistoricalOps.toString() +UnflaggedApi: android.app.AppOpsManager.HistoricalPackageOps#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.AppOpsManager.HistoricalPackageOps.equals(Object) +UnflaggedApi: android.app.AppOpsManager.HistoricalPackageOps#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.AppOpsManager.HistoricalPackageOps.hashCode() +UnflaggedApi: android.app.AppOpsManager.HistoricalUidOps#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.AppOpsManager.HistoricalUidOps.equals(Object) +UnflaggedApi: android.app.AppOpsManager.HistoricalUidOps#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.AppOpsManager.HistoricalUidOps.hashCode() +UnflaggedApi: android.app.GameModeConfiguration#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.GameModeConfiguration.equals(Object) +UnflaggedApi: android.app.GameModeConfiguration#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.GameModeConfiguration.hashCode() +UnflaggedApi: android.app.StatusBarManager.DisableInfo#toString(): + New API must be flagged with @FlaggedApi: method android.app.StatusBarManager.DisableInfo.toString() +UnflaggedApi: android.app.Vr2dDisplayProperties#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.Vr2dDisplayProperties.equals(Object) +UnflaggedApi: android.app.Vr2dDisplayProperties#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.Vr2dDisplayProperties.hashCode() +UnflaggedApi: android.app.Vr2dDisplayProperties#toString(): + New API must be flagged with @FlaggedApi: method android.app.Vr2dDisplayProperties.toString() +UnflaggedApi: android.app.admin.AccountTypePolicyKey#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.AccountTypePolicyKey.equals(Object) +UnflaggedApi: android.app.admin.AccountTypePolicyKey#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.AccountTypePolicyKey.hashCode() +UnflaggedApi: android.app.admin.AccountTypePolicyKey#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.AccountTypePolicyKey.toString() +UnflaggedApi: android.app.admin.Authority#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.Authority.equals(Object) +UnflaggedApi: android.app.admin.Authority#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.Authority.hashCode() +UnflaggedApi: android.app.admin.DeviceAdminAuthority#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.DeviceAdminAuthority.equals(Object) +UnflaggedApi: android.app.admin.DeviceAdminAuthority#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.DeviceAdminAuthority.hashCode() +UnflaggedApi: android.app.admin.DeviceAdminAuthority#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.DeviceAdminAuthority.toString() +UnflaggedApi: android.app.admin.DevicePolicyDrawableResource#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.DevicePolicyDrawableResource.equals(Object) +UnflaggedApi: android.app.admin.DevicePolicyDrawableResource#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.DevicePolicyDrawableResource.hashCode() +UnflaggedApi: android.app.admin.DevicePolicyKeyguardService#onDestroy(): + New API must be flagged with @FlaggedApi: method android.app.admin.DevicePolicyKeyguardService.onDestroy() +UnflaggedApi: android.app.admin.DevicePolicyResources.Strings: + New API must be flagged with @FlaggedApi: class android.app.admin.DevicePolicyResources.Strings +UnflaggedApi: android.app.admin.DevicePolicyResources.Strings.DefaultAppSettings: + New API must be flagged with @FlaggedApi: class android.app.admin.DevicePolicyResources.Strings.DefaultAppSettings +UnflaggedApi: android.app.admin.DevicePolicyResources.Strings.DefaultAppSettings#HOME_MISSING_WORK_PROFILE_SUPPORT_MESSAGE: + New API must be flagged with @FlaggedApi: field android.app.admin.DevicePolicyResources.Strings.DefaultAppSettings.HOME_MISSING_WORK_PROFILE_SUPPORT_MESSAGE +UnflaggedApi: android.app.admin.DevicePolicyResources.Strings.DefaultAppSettings#WORK_PROFILE_DEFAULT_APPS_TITLE: + New API must be flagged with @FlaggedApi: field android.app.admin.DevicePolicyResources.Strings.DefaultAppSettings.WORK_PROFILE_DEFAULT_APPS_TITLE +UnflaggedApi: android.app.admin.DevicePolicyResources.Strings.PermissionSettings: + New API must be flagged with @FlaggedApi: class android.app.admin.DevicePolicyResources.Strings.PermissionSettings +UnflaggedApi: android.app.admin.DevicePolicyResources.Strings.PermissionSettings#BACKGROUND_ACCESS_DISABLED_BY_ADMIN_MESSAGE: + New API must be flagged with @FlaggedApi: field android.app.admin.DevicePolicyResources.Strings.PermissionSettings.BACKGROUND_ACCESS_DISABLED_BY_ADMIN_MESSAGE +UnflaggedApi: android.app.admin.DevicePolicyResources.Strings.PermissionSettings#BACKGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE: + New API must be flagged with @FlaggedApi: field android.app.admin.DevicePolicyResources.Strings.PermissionSettings.BACKGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE +UnflaggedApi: android.app.admin.DevicePolicyResources.Strings.PermissionSettings#FOREGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE: + New API must be flagged with @FlaggedApi: field android.app.admin.DevicePolicyResources.Strings.PermissionSettings.FOREGROUND_ACCESS_ENABLED_BY_ADMIN_MESSAGE +UnflaggedApi: android.app.admin.DevicePolicyResources.Strings.PermissionSettings#LOCATION_AUTO_GRANTED_MESSAGE: + New API must be flagged with @FlaggedApi: field android.app.admin.DevicePolicyResources.Strings.PermissionSettings.LOCATION_AUTO_GRANTED_MESSAGE +UnflaggedApi: android.app.admin.DevicePolicyState#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.DevicePolicyState.toString() +UnflaggedApi: android.app.admin.DevicePolicyStringResource#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.DevicePolicyStringResource.equals(Object) +UnflaggedApi: android.app.admin.DevicePolicyStringResource#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.DevicePolicyStringResource.hashCode() +UnflaggedApi: android.app.admin.DpcAuthority#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.DpcAuthority.equals(Object) +UnflaggedApi: android.app.admin.DpcAuthority#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.DpcAuthority.hashCode() +UnflaggedApi: android.app.admin.DpcAuthority#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.DpcAuthority.toString() +UnflaggedApi: android.app.admin.EnforcingAdmin#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.EnforcingAdmin.equals(Object) +UnflaggedApi: android.app.admin.EnforcingAdmin#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.EnforcingAdmin.hashCode() +UnflaggedApi: android.app.admin.EnforcingAdmin#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.EnforcingAdmin.toString() +UnflaggedApi: android.app.admin.IntentFilterPolicyKey#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.IntentFilterPolicyKey.equals(Object) +UnflaggedApi: android.app.admin.IntentFilterPolicyKey#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.IntentFilterPolicyKey.hashCode() +UnflaggedApi: android.app.admin.IntentFilterPolicyKey#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.IntentFilterPolicyKey.toString() +UnflaggedApi: android.app.admin.LockTaskPolicy#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.LockTaskPolicy.equals(Object) +UnflaggedApi: android.app.admin.LockTaskPolicy#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.LockTaskPolicy.hashCode() +UnflaggedApi: android.app.admin.LockTaskPolicy#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.LockTaskPolicy.toString() +UnflaggedApi: android.app.admin.NoArgsPolicyKey#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.NoArgsPolicyKey.toString() +UnflaggedApi: android.app.admin.PackagePermissionPolicyKey#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.PackagePermissionPolicyKey.equals(Object) +UnflaggedApi: android.app.admin.PackagePermissionPolicyKey#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.PackagePermissionPolicyKey.hashCode() +UnflaggedApi: android.app.admin.PackagePermissionPolicyKey#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.PackagePermissionPolicyKey.toString() +UnflaggedApi: android.app.admin.PackagePolicyKey#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.PackagePolicyKey.equals(Object) +UnflaggedApi: android.app.admin.PackagePolicyKey#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.PackagePolicyKey.hashCode() +UnflaggedApi: android.app.admin.PackagePolicyKey#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.PackagePolicyKey.toString() +UnflaggedApi: android.app.admin.PolicyKey#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.PolicyKey.equals(Object) +UnflaggedApi: android.app.admin.PolicyKey#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.PolicyKey.hashCode() +UnflaggedApi: android.app.admin.PolicyState#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.PolicyState.toString() +UnflaggedApi: android.app.admin.RoleAuthority#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.RoleAuthority.equals(Object) +UnflaggedApi: android.app.admin.RoleAuthority#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.RoleAuthority.hashCode() +UnflaggedApi: android.app.admin.RoleAuthority#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.RoleAuthority.toString() +UnflaggedApi: android.app.admin.UnknownAuthority#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.admin.UnknownAuthority.equals(Object) +UnflaggedApi: android.app.admin.UnknownAuthority#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.admin.UnknownAuthority.hashCode() +UnflaggedApi: android.app.admin.UnknownAuthority#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.UnknownAuthority.toString() +UnflaggedApi: android.app.admin.UserRestrictionPolicyKey#toString(): + New API must be flagged with @FlaggedApi: method android.app.admin.UserRestrictionPolicyKey.toString() +UnflaggedApi: android.app.ambientcontext.AmbientContextEvent#toString(): + New API must be flagged with @FlaggedApi: method android.app.ambientcontext.AmbientContextEvent.toString() +UnflaggedApi: android.app.ambientcontext.AmbientContextEventRequest#toString(): + New API must be flagged with @FlaggedApi: method android.app.ambientcontext.AmbientContextEventRequest.toString() +UnflaggedApi: android.app.assist.ActivityId#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.assist.ActivityId.equals(Object) +UnflaggedApi: android.app.assist.ActivityId#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.assist.ActivityId.hashCode() +UnflaggedApi: android.app.assist.ActivityId#toString(): + New API must be flagged with @FlaggedApi: method android.app.assist.ActivityId.toString() +UnflaggedApi: android.app.assist.AssistStructure.ViewNode#ViewNode(): + New API must be flagged with @FlaggedApi: constructor android.app.assist.AssistStructure.ViewNode() +UnflaggedApi: android.app.backup.RestoreDescription#toString(): + New API must be flagged with @FlaggedApi: method android.app.backup.RestoreDescription.toString() +UnflaggedApi: android.app.cloudsearch.SearchRequest#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.cloudsearch.SearchRequest.equals(Object) +UnflaggedApi: android.app.cloudsearch.SearchRequest#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.cloudsearch.SearchRequest.hashCode() +UnflaggedApi: android.app.cloudsearch.SearchRequest#toString(): + New API must be flagged with @FlaggedApi: method android.app.cloudsearch.SearchRequest.toString() +UnflaggedApi: android.app.cloudsearch.SearchResponse#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.cloudsearch.SearchResponse.equals(Object) +UnflaggedApi: android.app.cloudsearch.SearchResponse#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.cloudsearch.SearchResponse.hashCode() +UnflaggedApi: android.app.cloudsearch.SearchResult#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.cloudsearch.SearchResult.equals(Object) +UnflaggedApi: android.app.cloudsearch.SearchResult#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.cloudsearch.SearchResult.hashCode() +UnflaggedApi: android.app.prediction.AppPredictionContext#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.prediction.AppPredictionContext.equals(Object) +UnflaggedApi: android.app.prediction.AppPredictionSessionId#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.prediction.AppPredictionSessionId.equals(Object) +UnflaggedApi: android.app.prediction.AppPredictionSessionId#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.prediction.AppPredictionSessionId.hashCode() +UnflaggedApi: android.app.prediction.AppPredictionSessionId#toString(): + New API must be flagged with @FlaggedApi: method android.app.prediction.AppPredictionSessionId.toString() +UnflaggedApi: android.app.prediction.AppPredictor#finalize(): + New API must be flagged with @FlaggedApi: method android.app.prediction.AppPredictor.finalize() +UnflaggedApi: android.app.prediction.AppTarget#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.prediction.AppTarget.equals(Object) +UnflaggedApi: android.app.prediction.AppTargetEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.prediction.AppTargetEvent.equals(Object) +UnflaggedApi: android.app.prediction.AppTargetId#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.prediction.AppTargetId.equals(Object) +UnflaggedApi: android.app.prediction.AppTargetId#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.prediction.AppTargetId.hashCode() +UnflaggedApi: android.app.search.SearchAction#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.search.SearchAction.equals(Object) +UnflaggedApi: android.app.search.SearchAction#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.search.SearchAction.hashCode() +UnflaggedApi: android.app.search.SearchAction#toString(): + New API must be flagged with @FlaggedApi: method android.app.search.SearchAction.toString() +UnflaggedApi: android.app.search.SearchSessionId#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.search.SearchSessionId.equals(Object) +UnflaggedApi: android.app.search.SearchSessionId#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.search.SearchSessionId.hashCode() +UnflaggedApi: android.app.search.SearchSessionId#toString(): + New API must be flagged with @FlaggedApi: method android.app.search.SearchSessionId.toString() +UnflaggedApi: android.app.search.SearchTargetEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.search.SearchTargetEvent.equals(Object) +UnflaggedApi: android.app.search.SearchTargetEvent#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.search.SearchTargetEvent.hashCode() +UnflaggedApi: android.app.smartspace.SmartspaceAction#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceAction.equals(Object) +UnflaggedApi: android.app.smartspace.SmartspaceAction#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceAction.hashCode() +UnflaggedApi: android.app.smartspace.SmartspaceAction#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceAction.toString() +UnflaggedApi: android.app.smartspace.SmartspaceConfig#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceConfig.equals(Object) +UnflaggedApi: android.app.smartspace.SmartspaceConfig#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceConfig.hashCode() +UnflaggedApi: android.app.smartspace.SmartspaceSessionId#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceSessionId.equals(Object) +UnflaggedApi: android.app.smartspace.SmartspaceSessionId#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceSessionId.hashCode() +UnflaggedApi: android.app.smartspace.SmartspaceSessionId#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceSessionId.toString() +UnflaggedApi: android.app.smartspace.SmartspaceTarget#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceTarget.equals(Object) +UnflaggedApi: android.app.smartspace.SmartspaceTarget#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceTarget.hashCode() +UnflaggedApi: android.app.smartspace.SmartspaceTarget#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceTarget.toString() +UnflaggedApi: android.app.smartspace.SmartspaceTargetEvent#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.SmartspaceTargetEvent.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.BaseTemplateData#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.BaseTemplateData.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.BaseTemplateData#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.BaseTemplateData.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.BaseTemplateData#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.BaseTemplateData.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemInfo.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemInfo.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemInfo#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemInfo.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemLoggingInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemLoggingInfo.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemLoggingInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemLoggingInfo.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemLoggingInfo#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.BaseTemplateData.SubItemLoggingInfo.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.CarouselTemplateData#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.CarouselTemplateData.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.CarouselTemplateData#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.CarouselTemplateData.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.CarouselTemplateData#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.CarouselTemplateData.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.CarouselTemplateData.CarouselItem#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.CarouselTemplateData.CarouselItem.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.CarouselTemplateData.CarouselItem#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.CarouselTemplateData.CarouselItem.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.CarouselTemplateData.CarouselItem#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.CarouselTemplateData.CarouselItem.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.CombinedCardsTemplateData#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.CombinedCardsTemplateData.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.CombinedCardsTemplateData#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.CombinedCardsTemplateData.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.CombinedCardsTemplateData#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.CombinedCardsTemplateData.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.HeadToHeadTemplateData#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.HeadToHeadTemplateData.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.HeadToHeadTemplateData#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.HeadToHeadTemplateData.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.HeadToHeadTemplateData#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.HeadToHeadTemplateData.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.Icon#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.Icon.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.Icon#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.Icon.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.Icon#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.Icon.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.SubCardTemplateData#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.SubCardTemplateData.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.SubCardTemplateData#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.SubCardTemplateData.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.SubCardTemplateData#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.SubCardTemplateData.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.SubImageTemplateData#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.SubImageTemplateData.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.SubImageTemplateData#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.SubImageTemplateData.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.SubImageTemplateData#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.SubImageTemplateData.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.SubListTemplateData#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.SubListTemplateData.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.SubListTemplateData#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.SubListTemplateData.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.SubListTemplateData#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.SubListTemplateData.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.TapAction#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.TapAction.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.TapAction#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.TapAction.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.TapAction#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.TapAction.toString() +UnflaggedApi: android.app.smartspace.uitemplatedata.Text#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.Text.equals(Object) +UnflaggedApi: android.app.smartspace.uitemplatedata.Text#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.Text.hashCode() +UnflaggedApi: android.app.smartspace.uitemplatedata.Text#toString(): + New API must be flagged with @FlaggedApi: method android.app.smartspace.uitemplatedata.Text.toString() +UnflaggedApi: android.app.time.ExternalTimeSuggestion#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.time.ExternalTimeSuggestion.equals(Object) +UnflaggedApi: android.app.time.ExternalTimeSuggestion#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.time.ExternalTimeSuggestion.hashCode() +UnflaggedApi: android.app.time.ExternalTimeSuggestion#toString(): + New API must be flagged with @FlaggedApi: method android.app.time.ExternalTimeSuggestion.toString() +UnflaggedApi: android.app.time.TimeCapabilities#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.time.TimeCapabilities.equals(Object) +UnflaggedApi: android.app.time.TimeCapabilities#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeCapabilities.hashCode() +UnflaggedApi: android.app.time.TimeCapabilities#toString(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeCapabilities.toString() +UnflaggedApi: android.app.time.TimeCapabilitiesAndConfig#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.time.TimeCapabilitiesAndConfig.equals(Object) +UnflaggedApi: android.app.time.TimeCapabilitiesAndConfig#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeCapabilitiesAndConfig.hashCode() +UnflaggedApi: android.app.time.TimeCapabilitiesAndConfig#toString(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeCapabilitiesAndConfig.toString() +UnflaggedApi: android.app.time.TimeConfiguration#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.time.TimeConfiguration.equals(Object) +UnflaggedApi: android.app.time.TimeConfiguration#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeConfiguration.hashCode() +UnflaggedApi: android.app.time.TimeConfiguration#toString(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeConfiguration.toString() +UnflaggedApi: android.app.time.TimeState#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.time.TimeState.equals(Object) +UnflaggedApi: android.app.time.TimeState#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeState.hashCode() +UnflaggedApi: android.app.time.TimeState#toString(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeState.toString() +UnflaggedApi: android.app.time.TimeZoneCapabilities#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneCapabilities.equals(Object) +UnflaggedApi: android.app.time.TimeZoneCapabilities#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneCapabilities.hashCode() +UnflaggedApi: android.app.time.TimeZoneCapabilities#toString(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneCapabilities.toString() +UnflaggedApi: android.app.time.TimeZoneCapabilitiesAndConfig#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneCapabilitiesAndConfig.equals(Object) +UnflaggedApi: android.app.time.TimeZoneCapabilitiesAndConfig#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneCapabilitiesAndConfig.hashCode() +UnflaggedApi: android.app.time.TimeZoneCapabilitiesAndConfig#toString(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneCapabilitiesAndConfig.toString() +UnflaggedApi: android.app.time.TimeZoneConfiguration#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneConfiguration.equals(Object) +UnflaggedApi: android.app.time.TimeZoneConfiguration#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneConfiguration.hashCode() +UnflaggedApi: android.app.time.TimeZoneConfiguration#toString(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneConfiguration.toString() +UnflaggedApi: android.app.time.TimeZoneState#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneState.equals(Object) +UnflaggedApi: android.app.time.TimeZoneState#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneState.hashCode() +UnflaggedApi: android.app.time.TimeZoneState#toString(): + New API must be flagged with @FlaggedApi: method android.app.time.TimeZoneState.toString() +UnflaggedApi: android.app.time.UnixEpochTime#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.time.UnixEpochTime.equals(Object) +UnflaggedApi: android.app.time.UnixEpochTime#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.time.UnixEpochTime.hashCode() +UnflaggedApi: android.app.time.UnixEpochTime#toString(): + New API must be flagged with @FlaggedApi: method android.app.time.UnixEpochTime.toString() +UnflaggedApi: android.app.usage.BroadcastResponseStats#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.usage.BroadcastResponseStats.equals(Object) +UnflaggedApi: android.app.usage.BroadcastResponseStats#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.usage.BroadcastResponseStats.hashCode() +UnflaggedApi: android.app.usage.BroadcastResponseStats#toString(): + New API must be flagged with @FlaggedApi: method android.app.usage.BroadcastResponseStats.toString() +UnflaggedApi: android.app.usage.CacheQuotaHint#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.usage.CacheQuotaHint.equals(Object) +UnflaggedApi: android.app.usage.CacheQuotaHint#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.usage.CacheQuotaHint.hashCode() +UnflaggedApi: android.app.usage.CacheQuotaService#onCreate(): + New API must be flagged with @FlaggedApi: method android.app.usage.CacheQuotaService.onCreate() +UnflaggedApi: android.app.usage.UsageEvents.Event#NOTIFICATION_INTERRUPTION: + New API must be flagged with @FlaggedApi: field android.app.usage.UsageEvents.Event.NOTIFICATION_INTERRUPTION +UnflaggedApi: android.app.usage.UsageEvents.Event#NOTIFICATION_SEEN: + New API must be flagged with @FlaggedApi: field android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN +UnflaggedApi: android.app.usage.UsageEvents.Event#SLICE_PINNED: + New API must be flagged with @FlaggedApi: field android.app.usage.UsageEvents.Event.SLICE_PINNED +UnflaggedApi: android.app.usage.UsageEvents.Event#SLICE_PINNED_PRIV: + New API must be flagged with @FlaggedApi: field android.app.usage.UsageEvents.Event.SLICE_PINNED_PRIV +UnflaggedApi: android.app.usage.UsageEvents.Event#SYSTEM_INTERACTION: + New API must be flagged with @FlaggedApi: field android.app.usage.UsageEvents.Event.SYSTEM_INTERACTION +UnflaggedApi: android.app.usage.UsageEvents.Event#getInstanceId(): + New API must be flagged with @FlaggedApi: method android.app.usage.UsageEvents.Event.getInstanceId() +UnflaggedApi: android.app.usage.UsageEvents.Event#getNotificationChannelId(): + New API must be flagged with @FlaggedApi: method android.app.usage.UsageEvents.Event.getNotificationChannelId() +UnflaggedApi: android.app.usage.UsageEvents.Event#getTaskRootClassName(): + New API must be flagged with @FlaggedApi: method android.app.usage.UsageEvents.Event.getTaskRootClassName() +UnflaggedApi: android.app.usage.UsageEvents.Event#getTaskRootPackageName(): + New API must be flagged with @FlaggedApi: method android.app.usage.UsageEvents.Event.getTaskRootPackageName() +UnflaggedApi: android.app.usage.UsageEvents.Event#isInstantApp(): + New API must be flagged with @FlaggedApi: method android.app.usage.UsageEvents.Event.isInstantApp() +UnflaggedApi: android.app.wallpapereffectsgeneration.CinematicEffectRequest#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.wallpapereffectsgeneration.CinematicEffectRequest.equals(Object) +UnflaggedApi: android.app.wallpapereffectsgeneration.CinematicEffectRequest#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.wallpapereffectsgeneration.CinematicEffectRequest.hashCode() +UnflaggedApi: android.app.wallpapereffectsgeneration.CinematicEffectResponse#equals(Object): + New API must be flagged with @FlaggedApi: method android.app.wallpapereffectsgeneration.CinematicEffectResponse.equals(Object) +UnflaggedApi: android.app.wallpapereffectsgeneration.CinematicEffectResponse#hashCode(): + New API must be flagged with @FlaggedApi: method android.app.wallpapereffectsgeneration.CinematicEffectResponse.hashCode() +UnflaggedApi: android.companion.virtual.VirtualDeviceManager.VirtualDevice#getPersistentDeviceId(): + New API must be flagged with @FlaggedApi: method android.companion.virtual.VirtualDeviceManager.VirtualDevice.getPersistentDeviceId() +UnflaggedApi: android.companion.virtual.VirtualDeviceParams#equals(Object): + New API must be flagged with @FlaggedApi: method android.companion.virtual.VirtualDeviceParams.equals(Object) +UnflaggedApi: android.companion.virtual.VirtualDeviceParams#hashCode(): + New API must be flagged with @FlaggedApi: method android.companion.virtual.VirtualDeviceParams.hashCode() +UnflaggedApi: android.companion.virtual.VirtualDeviceParams#toString(): + New API must be flagged with @FlaggedApi: method android.companion.virtual.VirtualDeviceParams.toString() +UnflaggedApi: android.companion.virtual.sensor.VirtualSensorConfig#toString(): + New API must be flagged with @FlaggedApi: method android.companion.virtual.sensor.VirtualSensorConfig.toString() +UnflaggedApi: android.content.Intent#ACTION_UNARCHIVE_PACKAGE: + New API must be flagged with @FlaggedApi: field android.content.Intent.ACTION_UNARCHIVE_PACKAGE +UnflaggedApi: android.content.integrity.Rule#equals(Object): + New API must be flagged with @FlaggedApi: method android.content.integrity.Rule.equals(Object) +UnflaggedApi: android.content.integrity.Rule#hashCode(): + New API must be flagged with @FlaggedApi: method android.content.integrity.Rule.hashCode() +UnflaggedApi: android.content.integrity.Rule#toString(): + New API must be flagged with @FlaggedApi: method android.content.integrity.Rule.toString() +UnflaggedApi: android.content.pm.PackageArchiver: + New API must be flagged with @FlaggedApi: class android.content.pm.PackageArchiver +UnflaggedApi: android.content.pm.PackageArchiver#EXTRA_UNARCHIVE_ALL_USERS: + New API must be flagged with @FlaggedApi: field android.content.pm.PackageArchiver.EXTRA_UNARCHIVE_ALL_USERS +UnflaggedApi: android.content.pm.PackageArchiver#EXTRA_UNARCHIVE_PACKAGE_NAME: + New API must be flagged with @FlaggedApi: field android.content.pm.PackageArchiver.EXTRA_UNARCHIVE_PACKAGE_NAME +UnflaggedApi: android.content.pm.PackageArchiver#requestArchive(String, android.content.IntentSender): + New API must be flagged with @FlaggedApi: method android.content.pm.PackageArchiver.requestArchive(String,android.content.IntentSender) +UnflaggedApi: android.content.pm.PackageArchiver#requestUnarchive(String): + New API must be flagged with @FlaggedApi: method android.content.pm.PackageArchiver.requestUnarchive(String) +UnflaggedApi: android.content.pm.PackageInfo#isArchived: + New API must be flagged with @FlaggedApi: field android.content.pm.PackageInfo.isArchived +UnflaggedApi: android.content.pm.PackageInstaller#readInstallInfo(android.os.ParcelFileDescriptor, String, int): + New API must be flagged with @FlaggedApi: method android.content.pm.PackageInstaller.readInstallInfo(android.os.ParcelFileDescriptor,String,int) +UnflaggedApi: android.content.pm.PackageInstaller.InstallInfo#calculateInstalledSize(android.content.pm.PackageInstaller.SessionParams, android.os.ParcelFileDescriptor): + New API must be flagged with @FlaggedApi: method android.content.pm.PackageInstaller.InstallInfo.calculateInstalledSize(android.content.pm.PackageInstaller.SessionParams,android.os.ParcelFileDescriptor) +UnflaggedApi: android.content.pm.PackageInstaller.SessionInfo#getResolvedBaseApkPath(): + New API must be flagged with @FlaggedApi: method android.content.pm.PackageInstaller.SessionInfo.getResolvedBaseApkPath() +UnflaggedApi: android.content.pm.PackageManager#EXTRA_REQUEST_PERMISSIONS_DEVICE_ID: + New API must be flagged with @FlaggedApi: field android.content.pm.PackageManager.EXTRA_REQUEST_PERMISSIONS_DEVICE_ID +UnflaggedApi: android.content.pm.PackageManager#MATCH_ARCHIVED_PACKAGES: + New API must be flagged with @FlaggedApi: field android.content.pm.PackageManager.MATCH_ARCHIVED_PACKAGES +UnflaggedApi: android.content.pm.PackageManager#getPackageArchiver(): + New API must be flagged with @FlaggedApi: method android.content.pm.PackageManager.getPackageArchiver() +UnflaggedApi: android.content.pm.SuspendDialogInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.content.pm.SuspendDialogInfo.equals(Object) +UnflaggedApi: android.content.pm.SuspendDialogInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.content.pm.SuspendDialogInfo.hashCode() +UnflaggedApi: android.content.pm.SuspendDialogInfo#toString(): + New API must be flagged with @FlaggedApi: method android.content.pm.SuspendDialogInfo.toString() +UnflaggedApi: android.content.pm.UserProperties#toString(): + New API must be flagged with @FlaggedApi: method android.content.pm.UserProperties.toString() +UnflaggedApi: android.content.pm.verify.domain.DomainOwner#equals(Object): + New API must be flagged with @FlaggedApi: method android.content.pm.verify.domain.DomainOwner.equals(Object) +UnflaggedApi: android.content.pm.verify.domain.DomainOwner#hashCode(): + New API must be flagged with @FlaggedApi: method android.content.pm.verify.domain.DomainOwner.hashCode() +UnflaggedApi: android.content.pm.verify.domain.DomainOwner#toString(): + New API must be flagged with @FlaggedApi: method android.content.pm.verify.domain.DomainOwner.toString() +UnflaggedApi: android.content.pm.verify.domain.DomainVerificationInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.content.pm.verify.domain.DomainVerificationInfo.equals(Object) +UnflaggedApi: android.content.pm.verify.domain.DomainVerificationInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.content.pm.verify.domain.DomainVerificationInfo.hashCode() +UnflaggedApi: android.content.pm.verify.domain.DomainVerificationInfo#toString(): + New API must be flagged with @FlaggedApi: method android.content.pm.verify.domain.DomainVerificationInfo.toString() +UnflaggedApi: android.content.pm.verify.domain.DomainVerificationRequest#equals(Object): + New API must be flagged with @FlaggedApi: method android.content.pm.verify.domain.DomainVerificationRequest.equals(Object) +UnflaggedApi: android.content.pm.verify.domain.DomainVerificationRequest#hashCode(): + New API must be flagged with @FlaggedApi: method android.content.pm.verify.domain.DomainVerificationRequest.hashCode() +UnflaggedApi: android.hardware.biometrics.BiometricManager.Authenticators#BIOMETRIC_CONVENIENCE: + New API must be flagged with @FlaggedApi: field android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE +UnflaggedApi: android.hardware.biometrics.BiometricManager.Authenticators#EMPTY_SET: + New API must be flagged with @FlaggedApi: field android.hardware.biometrics.BiometricManager.Authenticators.EMPTY_SET +UnflaggedApi: android.hardware.display.AmbientBrightnessDayStats#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.display.AmbientBrightnessDayStats.equals(Object) +UnflaggedApi: android.hardware.display.AmbientBrightnessDayStats#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.display.AmbientBrightnessDayStats.hashCode() +UnflaggedApi: android.hardware.display.AmbientBrightnessDayStats#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.display.AmbientBrightnessDayStats.toString() +UnflaggedApi: android.hardware.display.BrightnessChangeEvent#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.display.BrightnessChangeEvent.toString() +UnflaggedApi: android.hardware.display.BrightnessConfiguration#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.display.BrightnessConfiguration.equals(Object) +UnflaggedApi: android.hardware.display.BrightnessConfiguration#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.display.BrightnessConfiguration.hashCode() +UnflaggedApi: android.hardware.display.BrightnessConfiguration#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.display.BrightnessConfiguration.toString() +UnflaggedApi: android.hardware.display.BrightnessCorrection#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.display.BrightnessCorrection.equals(Object) +UnflaggedApi: android.hardware.display.BrightnessCorrection#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.display.BrightnessCorrection.hashCode() +UnflaggedApi: android.hardware.display.BrightnessCorrection#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.display.BrightnessCorrection.toString() +UnflaggedApi: android.hardware.hdmi.HdmiDeviceInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.hdmi.HdmiDeviceInfo.equals(Object) +UnflaggedApi: android.hardware.hdmi.HdmiDeviceInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.hdmi.HdmiDeviceInfo.hashCode() +UnflaggedApi: android.hardware.hdmi.HdmiDeviceInfo#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.hdmi.HdmiDeviceInfo.toString() +UnflaggedApi: android.hardware.hdmi.HdmiPortInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.hdmi.HdmiPortInfo.equals(Object) +UnflaggedApi: android.hardware.hdmi.HdmiPortInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.hdmi.HdmiPortInfo.hashCode() +UnflaggedApi: android.hardware.hdmi.HdmiPortInfo#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.hdmi.HdmiPortInfo.toString() +UnflaggedApi: android.hardware.location.ContextHubClient#finalize(): + New API must be flagged with @FlaggedApi: method android.hardware.location.ContextHubClient.finalize() +UnflaggedApi: android.hardware.location.ContextHubInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.location.ContextHubInfo.equals(Object) +UnflaggedApi: android.hardware.location.ContextHubInfo#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.location.ContextHubInfo.toString() +UnflaggedApi: android.hardware.location.ContextHubIntentEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.location.ContextHubIntentEvent.equals(Object) +UnflaggedApi: android.hardware.location.ContextHubIntentEvent#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.location.ContextHubIntentEvent.toString() +UnflaggedApi: android.hardware.location.ContextHubMessage#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.location.ContextHubMessage.toString() +UnflaggedApi: android.hardware.location.GeofenceHardwareMonitorEvent#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.location.GeofenceHardwareMonitorEvent.toString() +UnflaggedApi: android.hardware.location.MemoryRegion#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.location.MemoryRegion.equals(Object) +UnflaggedApi: android.hardware.location.MemoryRegion#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.location.MemoryRegion.toString() +UnflaggedApi: android.hardware.location.NanoApp#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.location.NanoApp.toString() +UnflaggedApi: android.hardware.location.NanoAppFilter#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.location.NanoAppFilter.toString() +UnflaggedApi: android.hardware.location.NanoAppInstanceInfo#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.location.NanoAppInstanceInfo.toString() +UnflaggedApi: android.hardware.location.NanoAppMessage#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.location.NanoAppMessage.equals(Object) +UnflaggedApi: android.hardware.location.NanoAppMessage#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.location.NanoAppMessage.toString() +UnflaggedApi: android.hardware.location.NanoAppRpcService#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.location.NanoAppRpcService.equals(Object) +UnflaggedApi: android.hardware.location.NanoAppRpcService#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.location.NanoAppRpcService.hashCode() +UnflaggedApi: android.hardware.location.NanoAppRpcService#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.location.NanoAppRpcService.toString() +UnflaggedApi: android.hardware.radio.ProgramList.Filter#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.ProgramList.Filter.equals(Object) +UnflaggedApi: android.hardware.radio.ProgramList.Filter#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.ProgramList.Filter.hashCode() +UnflaggedApi: android.hardware.radio.ProgramList.Filter#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.ProgramList.Filter.toString() +UnflaggedApi: android.hardware.radio.ProgramSelector#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.ProgramSelector.equals(Object) +UnflaggedApi: android.hardware.radio.ProgramSelector#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.ProgramSelector.hashCode() +UnflaggedApi: android.hardware.radio.ProgramSelector#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.ProgramSelector.toString() +UnflaggedApi: android.hardware.radio.ProgramSelector.Identifier#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.ProgramSelector.Identifier.equals(Object) +UnflaggedApi: android.hardware.radio.ProgramSelector.Identifier#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.ProgramSelector.Identifier.hashCode() +UnflaggedApi: android.hardware.radio.ProgramSelector.Identifier#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.ProgramSelector.Identifier.toString() +UnflaggedApi: android.hardware.radio.RadioManager.AmBandConfig#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.AmBandConfig.equals(Object) +UnflaggedApi: android.hardware.radio.RadioManager.AmBandConfig#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.AmBandConfig.hashCode() +UnflaggedApi: android.hardware.radio.RadioManager.AmBandConfig#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.AmBandConfig.toString() +UnflaggedApi: android.hardware.radio.RadioManager.AmBandDescriptor#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.AmBandDescriptor.equals(Object) +UnflaggedApi: android.hardware.radio.RadioManager.AmBandDescriptor#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.AmBandDescriptor.hashCode() +UnflaggedApi: android.hardware.radio.RadioManager.AmBandDescriptor#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.AmBandDescriptor.toString() +UnflaggedApi: android.hardware.radio.RadioManager.BandConfig#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.BandConfig.equals(Object) +UnflaggedApi: android.hardware.radio.RadioManager.BandConfig#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.BandConfig.hashCode() +UnflaggedApi: android.hardware.radio.RadioManager.BandConfig#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.BandConfig.toString() +UnflaggedApi: android.hardware.radio.RadioManager.BandDescriptor#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.BandDescriptor.equals(Object) +UnflaggedApi: android.hardware.radio.RadioManager.BandDescriptor#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.BandDescriptor.hashCode() +UnflaggedApi: android.hardware.radio.RadioManager.BandDescriptor#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.BandDescriptor.toString() +UnflaggedApi: android.hardware.radio.RadioManager.FmBandConfig#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.FmBandConfig.equals(Object) +UnflaggedApi: android.hardware.radio.RadioManager.FmBandConfig#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.FmBandConfig.hashCode() +UnflaggedApi: android.hardware.radio.RadioManager.FmBandConfig#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.FmBandConfig.toString() +UnflaggedApi: android.hardware.radio.RadioManager.FmBandDescriptor#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.FmBandDescriptor.equals(Object) +UnflaggedApi: android.hardware.radio.RadioManager.FmBandDescriptor#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.FmBandDescriptor.hashCode() +UnflaggedApi: android.hardware.radio.RadioManager.FmBandDescriptor#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.FmBandDescriptor.toString() +UnflaggedApi: android.hardware.radio.RadioManager.ModuleProperties#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.ModuleProperties.equals(Object) +UnflaggedApi: android.hardware.radio.RadioManager.ModuleProperties#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.ModuleProperties.hashCode() +UnflaggedApi: android.hardware.radio.RadioManager.ModuleProperties#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.ModuleProperties.toString() +UnflaggedApi: android.hardware.radio.RadioManager.ProgramInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.ProgramInfo.equals(Object) +UnflaggedApi: android.hardware.radio.RadioManager.ProgramInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.ProgramInfo.hashCode() +UnflaggedApi: android.hardware.radio.RadioManager.ProgramInfo#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioManager.ProgramInfo.toString() +UnflaggedApi: android.hardware.radio.RadioMetadata#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioMetadata.equals(Object) +UnflaggedApi: android.hardware.radio.RadioMetadata#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioMetadata.hashCode() +UnflaggedApi: android.hardware.radio.RadioMetadata#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.radio.RadioMetadata.toString() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.Keyphrase#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.Keyphrase.equals(Object) +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.Keyphrase#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.Keyphrase.hashCode() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.Keyphrase#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.Keyphrase.toString() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra.equals(Object) +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra.hashCode() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.KeyphraseRecognitionExtra.toString() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel.equals(Object) +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel.hashCode() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel.toString() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.ModelParamRange#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.ModelParamRange.equals(Object) +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.ModelParamRange#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.ModelParamRange.toString() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.ModuleProperties#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.ModuleProperties.equals(Object) +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.ModuleProperties#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.ModuleProperties.hashCode() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.ModuleProperties#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.ModuleProperties.toString() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.RecognitionEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.RecognitionEvent.equals(Object) +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.RecognitionEvent#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.RecognitionEvent.hashCode() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.RecognitionEvent#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.RecognitionEvent.toString() +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.SoundModel#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.SoundModel.equals(Object) +UnflaggedApi: android.hardware.soundtrigger.SoundTrigger.SoundModel#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.soundtrigger.SoundTrigger.SoundModel.hashCode() +UnflaggedApi: android.hardware.usb.DisplayPortAltModeInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.hardware.usb.DisplayPortAltModeInfo.equals(Object) +UnflaggedApi: android.hardware.usb.DisplayPortAltModeInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.hardware.usb.DisplayPortAltModeInfo.hashCode() +UnflaggedApi: android.hardware.usb.DisplayPortAltModeInfo#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.usb.DisplayPortAltModeInfo.toString() +UnflaggedApi: android.hardware.usb.UsbPort#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.usb.UsbPort.toString() +UnflaggedApi: android.hardware.usb.UsbPortStatus#toString(): + New API must be flagged with @FlaggedApi: method android.hardware.usb.UsbPortStatus.toString() +UnflaggedApi: android.location.CorrelationVector#equals(Object): + New API must be flagged with @FlaggedApi: method android.location.CorrelationVector.equals(Object) +UnflaggedApi: android.location.CorrelationVector#hashCode(): + New API must be flagged with @FlaggedApi: method android.location.CorrelationVector.hashCode() +UnflaggedApi: android.location.CorrelationVector#toString(): + New API must be flagged with @FlaggedApi: method android.location.CorrelationVector.toString() +UnflaggedApi: android.location.Country#equals(Object): + New API must be flagged with @FlaggedApi: method android.location.Country.equals(Object) +UnflaggedApi: android.location.Country#hashCode(): + New API must be flagged with @FlaggedApi: method android.location.Country.hashCode() +UnflaggedApi: android.location.Country#toString(): + New API must be flagged with @FlaggedApi: method android.location.Country.toString() +UnflaggedApi: android.location.GnssExcessPathInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.location.GnssExcessPathInfo.equals(Object) +UnflaggedApi: android.location.GnssExcessPathInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.location.GnssExcessPathInfo.hashCode() +UnflaggedApi: android.location.GnssExcessPathInfo#toString(): + New API must be flagged with @FlaggedApi: method android.location.GnssExcessPathInfo.toString() +UnflaggedApi: android.location.GnssMeasurementCorrections#toString(): + New API must be flagged with @FlaggedApi: method android.location.GnssMeasurementCorrections.toString() +UnflaggedApi: android.location.GnssMeasurementRequest#getWorkSource(): + New API must be flagged with @FlaggedApi: method android.location.GnssMeasurementRequest.getWorkSource() +UnflaggedApi: android.location.GnssMeasurementRequest.Builder#setWorkSource(android.os.WorkSource): + New API must be flagged with @FlaggedApi: method android.location.GnssMeasurementRequest.Builder.setWorkSource(android.os.WorkSource) +UnflaggedApi: android.location.GnssReflectingPlane#equals(Object): + New API must be flagged with @FlaggedApi: method android.location.GnssReflectingPlane.equals(Object) +UnflaggedApi: android.location.GnssReflectingPlane#hashCode(): + New API must be flagged with @FlaggedApi: method android.location.GnssReflectingPlane.hashCode() +UnflaggedApi: android.location.GnssReflectingPlane#toString(): + New API must be flagged with @FlaggedApi: method android.location.GnssReflectingPlane.toString() +UnflaggedApi: android.location.GnssRequest#equals(Object): + New API must be flagged with @FlaggedApi: method android.location.GnssRequest.equals(Object) +UnflaggedApi: android.location.GnssRequest#hashCode(): + New API must be flagged with @FlaggedApi: method android.location.GnssRequest.hashCode() +UnflaggedApi: android.location.GnssRequest#toString(): + New API must be flagged with @FlaggedApi: method android.location.GnssRequest.toString() +UnflaggedApi: android.location.GnssSingleSatCorrection#equals(Object): + New API must be flagged with @FlaggedApi: method android.location.GnssSingleSatCorrection.equals(Object) +UnflaggedApi: android.location.GnssSingleSatCorrection#hashCode(): + New API must be flagged with @FlaggedApi: method android.location.GnssSingleSatCorrection.hashCode() +UnflaggedApi: android.location.GnssSingleSatCorrection#toString(): + New API must be flagged with @FlaggedApi: method android.location.GnssSingleSatCorrection.toString() +UnflaggedApi: android.location.GpsClock#toString(): + New API must be flagged with @FlaggedApi: method android.location.GpsClock.toString() +UnflaggedApi: android.location.GpsMeasurement#toString(): + New API must be flagged with @FlaggedApi: method android.location.GpsMeasurement.toString() +UnflaggedApi: android.location.GpsMeasurementsEvent#toString(): + New API must be flagged with @FlaggedApi: method android.location.GpsMeasurementsEvent.toString() +UnflaggedApi: android.location.GpsNavigationMessage#toString(): + New API must be flagged with @FlaggedApi: method android.location.GpsNavigationMessage.toString() +UnflaggedApi: android.location.GpsNavigationMessageEvent#toString(): + New API must be flagged with @FlaggedApi: method android.location.GpsNavigationMessageEvent.toString() +UnflaggedApi: android.location.LastLocationRequest#equals(Object): + New API must be flagged with @FlaggedApi: method android.location.LastLocationRequest.equals(Object) +UnflaggedApi: android.location.LastLocationRequest#hashCode(): + New API must be flagged with @FlaggedApi: method android.location.LastLocationRequest.hashCode() +UnflaggedApi: android.location.LastLocationRequest#toString(): + New API must be flagged with @FlaggedApi: method android.location.LastLocationRequest.toString() +UnflaggedApi: android.location.SatellitePvt#toString(): + New API must be flagged with @FlaggedApi: method android.location.SatellitePvt.toString() +UnflaggedApi: android.location.SatellitePvt.ClockInfo#toString(): + New API must be flagged with @FlaggedApi: method android.location.SatellitePvt.ClockInfo.toString() +UnflaggedApi: android.location.SatellitePvt.PositionEcef#toString(): + New API must be flagged with @FlaggedApi: method android.location.SatellitePvt.PositionEcef.toString() +UnflaggedApi: android.location.SatellitePvt.VelocityEcef#toString(): + New API must be flagged with @FlaggedApi: method android.location.SatellitePvt.VelocityEcef.toString() +UnflaggedApi: android.location.provider.ProviderRequest#equals(Object): + New API must be flagged with @FlaggedApi: method android.location.provider.ProviderRequest.equals(Object) +UnflaggedApi: android.location.provider.ProviderRequest#hashCode(): + New API must be flagged with @FlaggedApi: method android.location.provider.ProviderRequest.hashCode() +UnflaggedApi: android.location.provider.ProviderRequest#toString(): + New API must be flagged with @FlaggedApi: method android.location.provider.ProviderRequest.toString() +UnflaggedApi: android.media.AudioDeviceAttributes#equals(Object): + New API must be flagged with @FlaggedApi: method android.media.AudioDeviceAttributes.equals(Object) +UnflaggedApi: android.media.AudioDeviceAttributes#hashCode(): + New API must be flagged with @FlaggedApi: method android.media.AudioDeviceAttributes.hashCode() +UnflaggedApi: android.media.AudioDeviceAttributes#toString(): + New API must be flagged with @FlaggedApi: method android.media.AudioDeviceAttributes.toString() +UnflaggedApi: android.media.AudioFocusInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.media.AudioFocusInfo.equals(Object) +UnflaggedApi: android.media.AudioFocusInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.media.AudioFocusInfo.hashCode() +UnflaggedApi: android.media.MediaRecorder.AudioSource#ECHO_REFERENCE: + New API must be flagged with @FlaggedApi: field android.media.MediaRecorder.AudioSource.ECHO_REFERENCE +UnflaggedApi: android.media.MediaRecorder.AudioSource#HOTWORD: + New API must be flagged with @FlaggedApi: field android.media.MediaRecorder.AudioSource.HOTWORD +UnflaggedApi: android.media.MediaRecorder.AudioSource#RADIO_TUNER: + New API must be flagged with @FlaggedApi: field android.media.MediaRecorder.AudioSource.RADIO_TUNER +UnflaggedApi: android.media.MediaRecorder.AudioSource#ULTRASOUND: + New API must be flagged with @FlaggedApi: field android.media.MediaRecorder.AudioSource.ULTRASOUND +UnflaggedApi: android.media.NearbyDevice#toString(): + New API must be flagged with @FlaggedApi: method android.media.NearbyDevice.toString() +UnflaggedApi: android.media.VolumeInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.media.VolumeInfo.equals(Object) +UnflaggedApi: android.media.VolumeInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.media.VolumeInfo.hashCode() +UnflaggedApi: android.media.VolumeInfo#toString(): + New API must be flagged with @FlaggedApi: method android.media.VolumeInfo.toString() +UnflaggedApi: android.media.audiopolicy.AudioMix#CREATOR: + New API must be flagged with @FlaggedApi: field android.media.audiopolicy.AudioMix.CREATOR +UnflaggedApi: android.media.audiopolicy.AudioMix#describeContents(): + New API must be flagged with @FlaggedApi: method android.media.audiopolicy.AudioMix.describeContents() +UnflaggedApi: android.media.audiopolicy.AudioMix#writeToParcel(android.os.Parcel, int): + New API must be flagged with @FlaggedApi: method android.media.audiopolicy.AudioMix.writeToParcel(android.os.Parcel,int) +UnflaggedApi: android.media.audiopolicy.AudioMixingRule#CREATOR: + New API must be flagged with @FlaggedApi: field android.media.audiopolicy.AudioMixingRule.CREATOR +UnflaggedApi: android.media.audiopolicy.AudioMixingRule#describeContents(): + New API must be flagged with @FlaggedApi: method android.media.audiopolicy.AudioMixingRule.describeContents() +UnflaggedApi: android.media.audiopolicy.AudioMixingRule#hashCode(): + New API must be flagged with @FlaggedApi: method android.media.audiopolicy.AudioMixingRule.hashCode() +UnflaggedApi: android.media.audiopolicy.AudioMixingRule#writeToParcel(android.os.Parcel, int): + New API must be flagged with @FlaggedApi: method android.media.audiopolicy.AudioMixingRule.writeToParcel(android.os.Parcel,int) +UnflaggedApi: android.media.audiopolicy.AudioPolicy#updateMixingRules(java.util.List<android.util.Pair<android.media.audiopolicy.AudioMix,android.media.audiopolicy.AudioMixingRule>>): + New API must be flagged with @FlaggedApi: method android.media.audiopolicy.AudioPolicy.updateMixingRules(java.util.List<android.util.Pair<android.media.audiopolicy.AudioMix,android.media.audiopolicy.AudioMixingRule>>) +UnflaggedApi: android.media.audiopolicy.AudioProductStrategy#equals(Object): + New API must be flagged with @FlaggedApi: method android.media.audiopolicy.AudioProductStrategy.equals(Object) +UnflaggedApi: android.media.audiopolicy.AudioProductStrategy#hashCode(): + New API must be flagged with @FlaggedApi: method android.media.audiopolicy.AudioProductStrategy.hashCode() +UnflaggedApi: android.media.audiopolicy.AudioProductStrategy#toString(): + New API must be flagged with @FlaggedApi: method android.media.audiopolicy.AudioProductStrategy.toString() +UnflaggedApi: android.media.audiopolicy.AudioVolumeGroup#equals(Object): + New API must be flagged with @FlaggedApi: method android.media.audiopolicy.AudioVolumeGroup.equals(Object) +UnflaggedApi: android.media.audiopolicy.AudioVolumeGroup#toString(): + New API must be flagged with @FlaggedApi: method android.media.audiopolicy.AudioVolumeGroup.toString() +UnflaggedApi: android.media.musicrecognition.MusicRecognitionService#onCreate(): + New API must be flagged with @FlaggedApi: method android.media.musicrecognition.MusicRecognitionService.onCreate() +UnflaggedApi: android.media.soundtrigger.SoundTriggerDetectionService#onUnbind(android.content.Intent): + New API must be flagged with @FlaggedApi: method android.media.soundtrigger.SoundTriggerDetectionService.onUnbind(android.content.Intent) +UnflaggedApi: android.media.tv.TunedInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.media.tv.TunedInfo.equals(Object) +UnflaggedApi: android.media.tv.TunedInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.media.tv.TunedInfo.hashCode() +UnflaggedApi: android.media.tv.TunedInfo#toString(): + New API must be flagged with @FlaggedApi: method android.media.tv.TunedInfo.toString() +UnflaggedApi: android.media.tv.TvInputHardwareInfo#toString(): + New API must be flagged with @FlaggedApi: method android.media.tv.TvInputHardwareInfo.toString() +UnflaggedApi: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle): + New API must be flagged with @FlaggedApi: method android.media.tv.TvRecordingClient.RecordingCallback.onEvent(String,String,android.os.Bundle) +UnflaggedApi: android.media.tv.TvStreamConfig#equals(Object): + New API must be flagged with @FlaggedApi: method android.media.tv.TvStreamConfig.equals(Object) +UnflaggedApi: android.media.tv.TvStreamConfig#toString(): + New API must be flagged with @FlaggedApi: method android.media.tv.TvStreamConfig.toString() +UnflaggedApi: android.net.MatchAllNetworkSpecifier#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.MatchAllNetworkSpecifier.equals(Object) +UnflaggedApi: android.net.MatchAllNetworkSpecifier#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.MatchAllNetworkSpecifier.hashCode() +UnflaggedApi: android.net.NetworkKey#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.NetworkKey.equals(Object) +UnflaggedApi: android.net.NetworkKey#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.NetworkKey.hashCode() +UnflaggedApi: android.net.NetworkKey#toString(): + New API must be flagged with @FlaggedApi: method android.net.NetworkKey.toString() +UnflaggedApi: android.net.RssiCurve#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.RssiCurve.equals(Object) +UnflaggedApi: android.net.RssiCurve#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.RssiCurve.hashCode() +UnflaggedApi: android.net.RssiCurve#toString(): + New API must be flagged with @FlaggedApi: method android.net.RssiCurve.toString() +UnflaggedApi: android.net.ScoredNetwork#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.ScoredNetwork.equals(Object) +UnflaggedApi: android.net.ScoredNetwork#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.ScoredNetwork.hashCode() +UnflaggedApi: android.net.ScoredNetwork#toString(): + New API must be flagged with @FlaggedApi: method android.net.ScoredNetwork.toString() +UnflaggedApi: android.net.WebAddress#toString(): + New API must be flagged with @FlaggedApi: method android.net.WebAddress.toString() +UnflaggedApi: android.net.WifiKey#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.WifiKey.equals(Object) +UnflaggedApi: android.net.WifiKey#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.WifiKey.hashCode() +UnflaggedApi: android.net.WifiKey#toString(): + New API must be flagged with @FlaggedApi: method android.net.WifiKey.toString() +UnflaggedApi: android.net.metrics.ApfProgramEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.metrics.ApfProgramEvent.equals(Object) +UnflaggedApi: android.net.metrics.ApfProgramEvent#toString(): + New API must be flagged with @FlaggedApi: method android.net.metrics.ApfProgramEvent.toString() +UnflaggedApi: android.net.metrics.ApfStats#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.metrics.ApfStats.equals(Object) +UnflaggedApi: android.net.metrics.ApfStats#toString(): + New API must be flagged with @FlaggedApi: method android.net.metrics.ApfStats.toString() +UnflaggedApi: android.net.metrics.DhcpClientEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.metrics.DhcpClientEvent.equals(Object) +UnflaggedApi: android.net.metrics.DhcpClientEvent#toString(): + New API must be flagged with @FlaggedApi: method android.net.metrics.DhcpClientEvent.toString() +UnflaggedApi: android.net.metrics.DhcpErrorEvent#toString(): + New API must be flagged with @FlaggedApi: method android.net.metrics.DhcpErrorEvent.toString() +UnflaggedApi: android.net.metrics.IpManagerEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.metrics.IpManagerEvent.equals(Object) +UnflaggedApi: android.net.metrics.IpManagerEvent#toString(): + New API must be flagged with @FlaggedApi: method android.net.metrics.IpManagerEvent.toString() +UnflaggedApi: android.net.metrics.IpReachabilityEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.metrics.IpReachabilityEvent.equals(Object) +UnflaggedApi: android.net.metrics.IpReachabilityEvent#toString(): + New API must be flagged with @FlaggedApi: method android.net.metrics.IpReachabilityEvent.toString() +UnflaggedApi: android.net.metrics.NetworkEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.metrics.NetworkEvent.equals(Object) +UnflaggedApi: android.net.metrics.NetworkEvent#toString(): + New API must be flagged with @FlaggedApi: method android.net.metrics.NetworkEvent.toString() +UnflaggedApi: android.net.metrics.RaEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.metrics.RaEvent.equals(Object) +UnflaggedApi: android.net.metrics.RaEvent#toString(): + New API must be flagged with @FlaggedApi: method android.net.metrics.RaEvent.toString() +UnflaggedApi: android.net.metrics.ValidationProbeEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.metrics.ValidationProbeEvent.equals(Object) +UnflaggedApi: android.net.metrics.ValidationProbeEvent#toString(): + New API must be flagged with @FlaggedApi: method android.net.metrics.ValidationProbeEvent.toString() +UnflaggedApi: android.net.vcn.VcnNetworkPolicyResult#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.vcn.VcnNetworkPolicyResult.equals(Object) +UnflaggedApi: android.net.vcn.VcnNetworkPolicyResult#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.vcn.VcnNetworkPolicyResult.hashCode() +UnflaggedApi: android.net.vcn.VcnNetworkPolicyResult#toString(): + New API must be flagged with @FlaggedApi: method android.net.vcn.VcnNetworkPolicyResult.toString() +UnflaggedApi: android.net.wifi.nl80211.DeviceWiphyCapabilities#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.wifi.nl80211.DeviceWiphyCapabilities.equals(Object) +UnflaggedApi: android.net.wifi.nl80211.DeviceWiphyCapabilities#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.wifi.nl80211.DeviceWiphyCapabilities.hashCode() +UnflaggedApi: android.net.wifi.nl80211.DeviceWiphyCapabilities#toString(): + New API must be flagged with @FlaggedApi: method android.net.wifi.nl80211.DeviceWiphyCapabilities.toString() +UnflaggedApi: android.net.wifi.nl80211.NativeWifiClient#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.wifi.nl80211.NativeWifiClient.equals(Object) +UnflaggedApi: android.net.wifi.nl80211.NativeWifiClient#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.wifi.nl80211.NativeWifiClient.hashCode() +UnflaggedApi: android.net.wifi.nl80211.PnoNetwork#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.wifi.nl80211.PnoNetwork.equals(Object) +UnflaggedApi: android.net.wifi.nl80211.PnoNetwork#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.wifi.nl80211.PnoNetwork.hashCode() +UnflaggedApi: android.net.wifi.nl80211.PnoSettings#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.wifi.nl80211.PnoSettings.equals(Object) +UnflaggedApi: android.net.wifi.nl80211.PnoSettings#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.wifi.nl80211.PnoSettings.hashCode() +UnflaggedApi: android.net.wifi.nl80211.RadioChainInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.wifi.nl80211.RadioChainInfo.equals(Object) +UnflaggedApi: android.net.wifi.nl80211.RadioChainInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.wifi.nl80211.RadioChainInfo.hashCode() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.HotspotNetwork#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.HotspotNetwork.equals(Object) +UnflaggedApi: android.net.wifi.sharedconnectivity.app.HotspotNetwork#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.HotspotNetwork.hashCode() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.HotspotNetwork#toString(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.HotspotNetwork.toString() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.equals(Object) +UnflaggedApi: android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.hashCode() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus#toString(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.HotspotNetworkConnectionStatus.toString() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.KnownNetwork#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.KnownNetwork.equals(Object) +UnflaggedApi: android.net.wifi.sharedconnectivity.app.KnownNetwork#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.KnownNetwork.hashCode() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.KnownNetwork#toString(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.KnownNetwork.toString() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.equals(Object) +UnflaggedApi: android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.hashCode() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus#toString(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.KnownNetworkConnectionStatus.toString() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.NetworkProviderInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.equals(Object) +UnflaggedApi: android.net.wifi.sharedconnectivity.app.NetworkProviderInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.hashCode() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.NetworkProviderInfo#isBatteryCharging(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.isBatteryCharging() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.NetworkProviderInfo#toString(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.toString() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder#setBatteryCharging(boolean): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.NetworkProviderInfo.Builder.setBatteryCharging(boolean) +UnflaggedApi: android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState#equals(Object): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState.equals(Object) +UnflaggedApi: android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState#hashCode(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState.hashCode() +UnflaggedApi: android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState#toString(): + New API must be flagged with @FlaggedApi: method android.net.wifi.sharedconnectivity.app.SharedConnectivitySettingsState.toString() +UnflaggedApi: android.os.BatterySaverPolicyConfig#toString(): + New API must be flagged with @FlaggedApi: method android.os.BatterySaverPolicyConfig.toString() +UnflaggedApi: android.os.BugreportParams#BUGREPORT_MODE_ONBOARDING: + New API must be flagged with @FlaggedApi: field android.os.BugreportParams.BUGREPORT_MODE_ONBOARDING +UnflaggedApi: android.os.Build.VERSION#KNOWN_CODENAMES: + New API must be flagged with @FlaggedApi: field android.os.Build.VERSION.KNOWN_CODENAMES +UnflaggedApi: android.os.Build.VERSION#PREVIEW_SDK_FINGERPRINT: + New API must be flagged with @FlaggedApi: field android.os.Build.VERSION.PREVIEW_SDK_FINGERPRINT +UnflaggedApi: android.os.IncidentManager.PendingReport#equals(Object): + New API must be flagged with @FlaggedApi: method android.os.IncidentManager.PendingReport.equals(Object) +UnflaggedApi: android.os.IncidentManager.PendingReport#toString(): + New API must be flagged with @FlaggedApi: method android.os.IncidentManager.PendingReport.toString() +UnflaggedApi: android.os.IncidentReportArgs#toString(): + New API must be flagged with @FlaggedApi: method android.os.IncidentReportArgs.toString() +UnflaggedApi: android.os.NewUserRequest#toString(): + New API must be flagged with @FlaggedApi: method android.os.NewUserRequest.toString() +UnflaggedApi: android.os.NewUserResponse#toString(): + New API must be flagged with @FlaggedApi: method android.os.NewUserResponse.toString() +UnflaggedApi: android.os.PowerManager.LowPowerStandbyPolicy#equals(Object): + New API must be flagged with @FlaggedApi: method android.os.PowerManager.LowPowerStandbyPolicy.equals(Object) +UnflaggedApi: android.os.PowerManager.LowPowerStandbyPolicy#hashCode(): + New API must be flagged with @FlaggedApi: method android.os.PowerManager.LowPowerStandbyPolicy.hashCode() +UnflaggedApi: android.os.PowerManager.LowPowerStandbyPolicy#toString(): + New API must be flagged with @FlaggedApi: method android.os.PowerManager.LowPowerStandbyPolicy.toString() +UnflaggedApi: android.os.PowerManager.LowPowerStandbyPortDescription#equals(Object): + New API must be flagged with @FlaggedApi: method android.os.PowerManager.LowPowerStandbyPortDescription.equals(Object) +UnflaggedApi: android.os.PowerManager.LowPowerStandbyPortDescription#hashCode(): + New API must be flagged with @FlaggedApi: method android.os.PowerManager.LowPowerStandbyPortDescription.hashCode() +UnflaggedApi: android.os.PowerManager.LowPowerStandbyPortDescription#toString(): + New API must be flagged with @FlaggedApi: method android.os.PowerManager.LowPowerStandbyPortDescription.toString() +UnflaggedApi: android.os.ServiceSpecificException#toString(): + New API must be flagged with @FlaggedApi: method android.os.ServiceSpecificException.toString() +UnflaggedApi: android.os.WorkSource.WorkChain#equals(Object): + New API must be flagged with @FlaggedApi: method android.os.WorkSource.WorkChain.equals(Object) +UnflaggedApi: android.os.WorkSource.WorkChain#hashCode(): + New API must be flagged with @FlaggedApi: method android.os.WorkSource.WorkChain.hashCode() +UnflaggedApi: android.os.WorkSource.WorkChain#toString(): + New API must be flagged with @FlaggedApi: method android.os.WorkSource.WorkChain.toString() +UnflaggedApi: android.os.connectivity.CellularBatteryStats#equals(Object): + New API must be flagged with @FlaggedApi: method android.os.connectivity.CellularBatteryStats.equals(Object) +UnflaggedApi: android.os.connectivity.CellularBatteryStats#hashCode(): + New API must be flagged with @FlaggedApi: method android.os.connectivity.CellularBatteryStats.hashCode() +UnflaggedApi: android.os.connectivity.WifiActivityEnergyInfo#toString(): + New API must be flagged with @FlaggedApi: method android.os.connectivity.WifiActivityEnergyInfo.toString() +UnflaggedApi: android.os.connectivity.WifiBatteryStats#equals(Object): + New API must be flagged with @FlaggedApi: method android.os.connectivity.WifiBatteryStats.equals(Object) +UnflaggedApi: android.os.connectivity.WifiBatteryStats#hashCode(): + New API must be flagged with @FlaggedApi: method android.os.connectivity.WifiBatteryStats.hashCode() +UnflaggedApi: android.permission.AdminPermissionControlParams#toString(): + New API must be flagged with @FlaggedApi: method android.permission.AdminPermissionControlParams.toString() +UnflaggedApi: android.permission.PermissionGroupUsage#equals(Object): + New API must be flagged with @FlaggedApi: method android.permission.PermissionGroupUsage.equals(Object) +UnflaggedApi: android.permission.PermissionGroupUsage#hashCode(): + New API must be flagged with @FlaggedApi: method android.permission.PermissionGroupUsage.hashCode() +UnflaggedApi: android.permission.PermissionGroupUsage#toString(): + New API must be flagged with @FlaggedApi: method android.permission.PermissionGroupUsage.toString() +UnflaggedApi: android.permission.PermissionManager.SplitPermissionInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.permission.PermissionManager.SplitPermissionInfo.equals(Object) +UnflaggedApi: android.permission.PermissionManager.SplitPermissionInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.permission.PermissionManager.SplitPermissionInfo.hashCode() +UnflaggedApi: android.printservice.PrintServiceInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.printservice.PrintServiceInfo.equals(Object) +UnflaggedApi: android.printservice.PrintServiceInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.printservice.PrintServiceInfo.hashCode() +UnflaggedApi: android.printservice.PrintServiceInfo#toString(): + New API must be flagged with @FlaggedApi: method android.printservice.PrintServiceInfo.toString() +UnflaggedApi: android.printservice.recommendation.RecommendationService#attachBaseContext(android.content.Context): + New API must be flagged with @FlaggedApi: method android.printservice.recommendation.RecommendationService.attachBaseContext(android.content.Context) +UnflaggedApi: android.provider.CallLog.CallComposerLoggingException#toString(): + New API must be flagged with @FlaggedApi: method android.provider.CallLog.CallComposerLoggingException.toString() +UnflaggedApi: android.provider.ContactsContract.MetadataSync#CONTENT_ITEM_TYPE: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSync.CONTENT_ITEM_TYPE +UnflaggedApi: android.provider.ContactsContract.MetadataSync#CONTENT_TYPE: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSync.CONTENT_TYPE +UnflaggedApi: android.provider.ContactsContract.MetadataSync#CONTENT_URI: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSync.CONTENT_URI +UnflaggedApi: android.provider.ContactsContract.MetadataSync#METADATA_AUTHORITY: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSync.METADATA_AUTHORITY +UnflaggedApi: android.provider.ContactsContract.MetadataSync#METADATA_AUTHORITY_URI: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSync.METADATA_AUTHORITY_URI +UnflaggedApi: android.provider.ContactsContract.MetadataSync#_COUNT: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSync._COUNT +UnflaggedApi: android.provider.ContactsContract.MetadataSync#_ID: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSync._ID +UnflaggedApi: android.provider.ContactsContract.MetadataSyncColumns#ACCOUNT_NAME: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncColumns.ACCOUNT_NAME +UnflaggedApi: android.provider.ContactsContract.MetadataSyncColumns#ACCOUNT_TYPE: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncColumns.ACCOUNT_TYPE +UnflaggedApi: android.provider.ContactsContract.MetadataSyncColumns#DATA: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncColumns.DATA +UnflaggedApi: android.provider.ContactsContract.MetadataSyncColumns#DATA_SET: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncColumns.DATA_SET +UnflaggedApi: android.provider.ContactsContract.MetadataSyncColumns#DELETED: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncColumns.DELETED +UnflaggedApi: android.provider.ContactsContract.MetadataSyncColumns#RAW_CONTACT_BACKUP_ID: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncColumns.RAW_CONTACT_BACKUP_ID +UnflaggedApi: android.provider.ContactsContract.MetadataSyncState#CONTENT_ITEM_TYPE: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncState.CONTENT_ITEM_TYPE +UnflaggedApi: android.provider.ContactsContract.MetadataSyncState#CONTENT_TYPE: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncState.CONTENT_TYPE +UnflaggedApi: android.provider.ContactsContract.MetadataSyncState#CONTENT_URI: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncState.CONTENT_URI +UnflaggedApi: android.provider.ContactsContract.MetadataSyncState#_COUNT: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncState._COUNT +UnflaggedApi: android.provider.ContactsContract.MetadataSyncState#_ID: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncState._ID +UnflaggedApi: android.provider.ContactsContract.MetadataSyncStateColumns#ACCOUNT_NAME: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncStateColumns.ACCOUNT_NAME +UnflaggedApi: android.provider.ContactsContract.MetadataSyncStateColumns#ACCOUNT_TYPE: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncStateColumns.ACCOUNT_TYPE +UnflaggedApi: android.provider.ContactsContract.MetadataSyncStateColumns#DATA_SET: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncStateColumns.DATA_SET +UnflaggedApi: android.provider.ContactsContract.MetadataSyncStateColumns#STATE: + New API must be flagged with @FlaggedApi: field android.provider.ContactsContract.MetadataSyncStateColumns.STATE +UnflaggedApi: android.provider.ContactsContract.Settings#setDefaultAccount(android.content.ContentResolver, android.accounts.Account): + New API must be flagged with @FlaggedApi: method android.provider.ContactsContract.Settings.setDefaultAccount(android.content.ContentResolver,android.accounts.Account) +UnflaggedApi: android.provider.ContactsContract.SimContacts#addSimAccount(android.content.ContentResolver, String, String, int, int): + New API must be flagged with @FlaggedApi: method android.provider.ContactsContract.SimContacts.addSimAccount(android.content.ContentResolver,String,String,int,int) +UnflaggedApi: android.provider.ContactsContract.SimContacts#removeSimAccounts(android.content.ContentResolver, int): + New API must be flagged with @FlaggedApi: method android.provider.ContactsContract.SimContacts.removeSimAccounts(android.content.ContentResolver,int) +UnflaggedApi: android.provider.SearchIndexableData#toString(): + New API must be flagged with @FlaggedApi: method android.provider.SearchIndexableData.toString() +UnflaggedApi: android.provider.SearchIndexableResource#toString(): + New API must be flagged with @FlaggedApi: method android.provider.SearchIndexableResource.toString() +UnflaggedApi: android.provider.SearchIndexablesProvider#attachInfo(android.content.Context, android.content.pm.ProviderInfo): + New API must be flagged with @FlaggedApi: method android.provider.SearchIndexablesProvider.attachInfo(android.content.Context,android.content.pm.ProviderInfo) +UnflaggedApi: android.provider.Settings#ACTION_APP_PERMISSIONS_SETTINGS: + New API must be flagged with @FlaggedApi: field android.provider.Settings.ACTION_APP_PERMISSIONS_SETTINGS +UnflaggedApi: android.provider.Settings.System#putString(android.content.ContentResolver, String, String, boolean, boolean): + New API must be flagged with @FlaggedApi: method android.provider.Settings.System.putString(android.content.ContentResolver,String,String,boolean,boolean) +UnflaggedApi: android.provider.Settings.System#resetToDefaults(android.content.ContentResolver, String): + New API must be flagged with @FlaggedApi: method android.provider.Settings.System.resetToDefaults(android.content.ContentResolver,String) +UnflaggedApi: android.provider.SimPhonebookContract.SimRecords#QUERY_ARG_PIN2: + New API must be flagged with @FlaggedApi: field android.provider.SimPhonebookContract.SimRecords.QUERY_ARG_PIN2 +UnflaggedApi: android.provider.Telephony.Carriers#APN_SET_ID: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.APN_SET_ID +UnflaggedApi: android.provider.Telephony.Carriers#CARRIER_EDITED: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.CARRIER_EDITED +UnflaggedApi: android.provider.Telephony.Carriers#EDITED_STATUS: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.EDITED_STATUS +UnflaggedApi: android.provider.Telephony.Carriers#MATCH_ALL_APN_SET_ID: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.MATCH_ALL_APN_SET_ID +UnflaggedApi: android.provider.Telephony.Carriers#MAX_CONNECTIONS: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.MAX_CONNECTIONS +UnflaggedApi: android.provider.Telephony.Carriers#MODEM_PERSIST: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.MODEM_PERSIST +UnflaggedApi: android.provider.Telephony.Carriers#MTU_V4: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.MTU_V4 +UnflaggedApi: android.provider.Telephony.Carriers#MTU_V6: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.MTU_V6 +UnflaggedApi: android.provider.Telephony.Carriers#NO_APN_SET_ID: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.NO_APN_SET_ID +UnflaggedApi: android.provider.Telephony.Carriers#TIME_LIMIT_FOR_MAX_CONNECTIONS: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.TIME_LIMIT_FOR_MAX_CONNECTIONS +UnflaggedApi: android.provider.Telephony.Carriers#UNEDITED: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.UNEDITED +UnflaggedApi: android.provider.Telephony.Carriers#USER_DELETED: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.USER_DELETED +UnflaggedApi: android.provider.Telephony.Carriers#USER_EDITABLE: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.USER_EDITABLE +UnflaggedApi: android.provider.Telephony.Carriers#USER_EDITED: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.USER_EDITED +UnflaggedApi: android.provider.Telephony.Carriers#USER_VISIBLE: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.USER_VISIBLE +UnflaggedApi: android.provider.Telephony.Carriers#WAIT_TIME_RETRY: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Carriers.WAIT_TIME_RETRY +UnflaggedApi: android.provider.Telephony.CellBroadcasts: + New API must be flagged with @FlaggedApi: class android.provider.Telephony.CellBroadcasts +UnflaggedApi: android.provider.Telephony.CellBroadcasts#AUTHORITY_LEGACY: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.AUTHORITY_LEGACY +UnflaggedApi: android.provider.Telephony.CellBroadcasts#AUTHORITY_LEGACY_URI: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.AUTHORITY_LEGACY_URI +UnflaggedApi: android.provider.Telephony.CellBroadcasts#CALL_METHOD_GET_PREFERENCE: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.CALL_METHOD_GET_PREFERENCE +UnflaggedApi: android.provider.Telephony.CellBroadcasts#CID: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.CID +UnflaggedApi: android.provider.Telephony.CellBroadcasts#CMAS_CATEGORY: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.CMAS_CATEGORY +UnflaggedApi: android.provider.Telephony.CellBroadcasts#CMAS_CERTAINTY: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.CMAS_CERTAINTY +UnflaggedApi: android.provider.Telephony.CellBroadcasts#CMAS_MESSAGE_CLASS: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.CMAS_MESSAGE_CLASS +UnflaggedApi: android.provider.Telephony.CellBroadcasts#CMAS_RESPONSE_TYPE: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.CMAS_RESPONSE_TYPE +UnflaggedApi: android.provider.Telephony.CellBroadcasts#CMAS_SEVERITY: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.CMAS_SEVERITY +UnflaggedApi: android.provider.Telephony.CellBroadcasts#CMAS_URGENCY: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.CMAS_URGENCY +UnflaggedApi: android.provider.Telephony.CellBroadcasts#CONTENT_URI: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.CONTENT_URI +UnflaggedApi: android.provider.Telephony.CellBroadcasts#DATA_CODING_SCHEME: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.DATA_CODING_SCHEME +UnflaggedApi: android.provider.Telephony.CellBroadcasts#DEFAULT_SORT_ORDER: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.DEFAULT_SORT_ORDER +UnflaggedApi: android.provider.Telephony.CellBroadcasts#DELIVERY_TIME: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.DELIVERY_TIME +UnflaggedApi: android.provider.Telephony.CellBroadcasts#ETWS_IS_PRIMARY: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.ETWS_IS_PRIMARY +UnflaggedApi: android.provider.Telephony.CellBroadcasts#ETWS_WARNING_TYPE: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.ETWS_WARNING_TYPE +UnflaggedApi: android.provider.Telephony.CellBroadcasts#GEOGRAPHICAL_SCOPE: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.GEOGRAPHICAL_SCOPE +UnflaggedApi: android.provider.Telephony.CellBroadcasts#GEOMETRIES: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.GEOMETRIES +UnflaggedApi: android.provider.Telephony.CellBroadcasts#LAC: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.LAC +UnflaggedApi: android.provider.Telephony.CellBroadcasts#LANGUAGE_CODE: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.LANGUAGE_CODE +UnflaggedApi: android.provider.Telephony.CellBroadcasts#LOCATION_CHECK_TIME: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.LOCATION_CHECK_TIME +UnflaggedApi: android.provider.Telephony.CellBroadcasts#MAXIMUM_WAIT_TIME: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.MAXIMUM_WAIT_TIME +UnflaggedApi: android.provider.Telephony.CellBroadcasts#MESSAGE_BODY: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.MESSAGE_BODY +UnflaggedApi: android.provider.Telephony.CellBroadcasts#MESSAGE_BROADCASTED: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.MESSAGE_BROADCASTED +UnflaggedApi: android.provider.Telephony.CellBroadcasts#MESSAGE_DISPLAYED: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.MESSAGE_DISPLAYED +UnflaggedApi: android.provider.Telephony.CellBroadcasts#MESSAGE_FORMAT: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.MESSAGE_FORMAT +UnflaggedApi: android.provider.Telephony.CellBroadcasts#MESSAGE_HISTORY_URI: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.MESSAGE_HISTORY_URI +UnflaggedApi: android.provider.Telephony.CellBroadcasts#MESSAGE_PRIORITY: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.MESSAGE_PRIORITY +UnflaggedApi: android.provider.Telephony.CellBroadcasts#MESSAGE_READ: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.MESSAGE_READ +UnflaggedApi: android.provider.Telephony.CellBroadcasts#PLMN: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.PLMN +UnflaggedApi: android.provider.Telephony.CellBroadcasts#RECEIVED_TIME: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.RECEIVED_TIME +UnflaggedApi: android.provider.Telephony.CellBroadcasts#SERIAL_NUMBER: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.SERIAL_NUMBER +UnflaggedApi: android.provider.Telephony.CellBroadcasts#SERVICE_CATEGORY: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.SERVICE_CATEGORY +UnflaggedApi: android.provider.Telephony.CellBroadcasts#SLOT_INDEX: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.SLOT_INDEX +UnflaggedApi: android.provider.Telephony.CellBroadcasts#SUBSCRIPTION_ID: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.SUBSCRIPTION_ID +UnflaggedApi: android.provider.Telephony.CellBroadcasts#_COUNT: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts._COUNT +UnflaggedApi: android.provider.Telephony.CellBroadcasts#_ID: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts._ID +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference: + New API must be flagged with @FlaggedApi: class android.provider.Telephony.CellBroadcasts.Preference +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference#ENABLE_ALERT_VIBRATION_PREF: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.Preference.ENABLE_ALERT_VIBRATION_PREF +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference#ENABLE_AREA_UPDATE_INFO_PREF: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.Preference.ENABLE_AREA_UPDATE_INFO_PREF +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference#ENABLE_CMAS_AMBER_PREF: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.Preference.ENABLE_CMAS_AMBER_PREF +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference#ENABLE_CMAS_EXTREME_THREAT_PREF: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.Preference.ENABLE_CMAS_EXTREME_THREAT_PREF +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference#ENABLE_CMAS_IN_SECOND_LANGUAGE_PREF: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.Preference.ENABLE_CMAS_IN_SECOND_LANGUAGE_PREF +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference#ENABLE_CMAS_PRESIDENTIAL_PREF: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.Preference.ENABLE_CMAS_PRESIDENTIAL_PREF +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference#ENABLE_CMAS_SEVERE_THREAT_PREF: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.Preference.ENABLE_CMAS_SEVERE_THREAT_PREF +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference#ENABLE_EMERGENCY_PERF: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.Preference.ENABLE_EMERGENCY_PERF +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference#ENABLE_PUBLIC_SAFETY_PREF: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.Preference.ENABLE_PUBLIC_SAFETY_PREF +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference#ENABLE_STATE_LOCAL_TEST_PREF: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.Preference.ENABLE_STATE_LOCAL_TEST_PREF +UnflaggedApi: android.provider.Telephony.CellBroadcasts.Preference#ENABLE_TEST_ALERT_PREF: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.CellBroadcasts.Preference.ENABLE_TEST_ALERT_PREF +UnflaggedApi: android.provider.Telephony.Sms.Intents#ACTION_SMS_EMERGENCY_CB_RECEIVED: + New API must be flagged with @FlaggedApi: field android.provider.Telephony.Sms.Intents.ACTION_SMS_EMERGENCY_CB_RECEIVED +UnflaggedApi: android.service.ambientcontext.AmbientContextDetectionResult#toString(): + New API must be flagged with @FlaggedApi: method android.service.ambientcontext.AmbientContextDetectionResult.toString() +UnflaggedApi: android.service.ambientcontext.AmbientContextDetectionServiceStatus#toString(): + New API must be flagged with @FlaggedApi: method android.service.ambientcontext.AmbientContextDetectionServiceStatus.toString() +UnflaggedApi: android.service.appprediction.AppPredictionService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.appprediction.AppPredictionService.onCreate() +UnflaggedApi: android.service.assist.classification.FieldClassificationRequest#toString(): + New API must be flagged with @FlaggedApi: method android.service.assist.classification.FieldClassificationRequest.toString() +UnflaggedApi: android.service.assist.classification.FieldClassificationResponse#toString(): + New API must be flagged with @FlaggedApi: method android.service.assist.classification.FieldClassificationResponse.toString() +UnflaggedApi: android.service.assist.classification.FieldClassificationService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.assist.classification.FieldClassificationService.onCreate() +UnflaggedApi: android.service.autofill.AutofillFieldClassificationService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.autofill.AutofillFieldClassificationService.onCreate() +UnflaggedApi: android.service.autofill.Dataset.Builder#setContent(android.view.autofill.AutofillId, android.content.ClipData): + New API must be flagged with @FlaggedApi: method android.service.autofill.Dataset.Builder.setContent(android.view.autofill.AutofillId,android.content.ClipData) +UnflaggedApi: android.service.autofill.augmented.AugmentedAutofillService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.autofill.augmented.AugmentedAutofillService.onCreate() +UnflaggedApi: android.service.autofill.augmented.AugmentedAutofillService#onUnbind(android.content.Intent): + New API must be flagged with @FlaggedApi: method android.service.autofill.augmented.AugmentedAutofillService.onUnbind(android.content.Intent) +UnflaggedApi: android.service.autofill.augmented.FillRequest#toString(): + New API must be flagged with @FlaggedApi: method android.service.autofill.augmented.FillRequest.toString() +UnflaggedApi: android.service.autofill.augmented.FillWindow#finalize(): + New API must be flagged with @FlaggedApi: method android.service.autofill.augmented.FillWindow.finalize() +UnflaggedApi: android.service.autofill.augmented.PresentationParams.Area#toString(): + New API must be flagged with @FlaggedApi: method android.service.autofill.augmented.PresentationParams.Area.toString() +UnflaggedApi: android.service.cloudsearch.CloudSearchService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.cloudsearch.CloudSearchService.onCreate() +UnflaggedApi: android.service.contentcapture.ActivityEvent#toString(): + New API must be flagged with @FlaggedApi: method android.service.contentcapture.ActivityEvent.toString() +UnflaggedApi: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]): + New API must be flagged with @FlaggedApi: method android.service.contentcapture.ContentCaptureService.dump(java.io.FileDescriptor,java.io.PrintWriter,String[]) +UnflaggedApi: android.service.contentcapture.ContentCaptureService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.contentcapture.ContentCaptureService.onCreate() +UnflaggedApi: android.service.contentsuggestions.ContentSuggestionsService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.contentsuggestions.ContentSuggestionsService.onCreate() +UnflaggedApi: android.service.displayhash.DisplayHashParams#toString(): + New API must be flagged with @FlaggedApi: method android.service.displayhash.DisplayHashParams.toString() +UnflaggedApi: android.service.displayhash.DisplayHashingService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.displayhash.DisplayHashingService.onCreate() +UnflaggedApi: android.service.euicc.EuiccProfileInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.euicc.EuiccProfileInfo.equals(Object) +UnflaggedApi: android.service.euicc.EuiccProfileInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.euicc.EuiccProfileInfo.hashCode() +UnflaggedApi: android.service.euicc.EuiccProfileInfo#toString(): + New API must be flagged with @FlaggedApi: method android.service.euicc.EuiccProfileInfo.toString() +UnflaggedApi: android.service.euicc.EuiccService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.euicc.EuiccService.onCreate() +UnflaggedApi: android.service.euicc.EuiccService#onDestroy(): + New API must be flagged with @FlaggedApi: method android.service.euicc.EuiccService.onDestroy() +UnflaggedApi: android.service.games.CreateGameSessionRequest#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.games.CreateGameSessionRequest.equals(Object) +UnflaggedApi: android.service.games.CreateGameSessionRequest#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.games.CreateGameSessionRequest.hashCode() +UnflaggedApi: android.service.games.CreateGameSessionRequest#toString(): + New API must be flagged with @FlaggedApi: method android.service.games.CreateGameSessionRequest.toString() +UnflaggedApi: android.service.games.GameSessionService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.games.GameSessionService.onCreate() +UnflaggedApi: android.service.games.GameStartedEvent#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.games.GameStartedEvent.equals(Object) +UnflaggedApi: android.service.games.GameStartedEvent#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.games.GameStartedEvent.hashCode() +UnflaggedApi: android.service.games.GameStartedEvent#toString(): + New API must be flagged with @FlaggedApi: method android.service.games.GameStartedEvent.toString() +UnflaggedApi: android.service.notification.Adjustment#toString(): + New API must be flagged with @FlaggedApi: method android.service.notification.Adjustment.toString() +UnflaggedApi: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context): + New API must be flagged with @FlaggedApi: method android.service.notification.NotificationAssistantService.attachBaseContext(android.content.Context) +UnflaggedApi: android.service.notification.NotificationStats#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.notification.NotificationStats.equals(Object) +UnflaggedApi: android.service.notification.NotificationStats#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.notification.NotificationStats.hashCode() +UnflaggedApi: android.service.notification.NotificationStats#toString(): + New API must be flagged with @FlaggedApi: method android.service.notification.NotificationStats.toString() +UnflaggedApi: android.service.notification.SnoozeCriterion#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.notification.SnoozeCriterion.equals(Object) +UnflaggedApi: android.service.notification.SnoozeCriterion#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.notification.SnoozeCriterion.hashCode() +UnflaggedApi: android.service.resolver.ResolverRankerService#onDestroy(): + New API must be flagged with @FlaggedApi: method android.service.resolver.ResolverRankerService.onDestroy() +UnflaggedApi: android.service.resolver.ResolverTarget#toString(): + New API must be flagged with @FlaggedApi: method android.service.resolver.ResolverTarget.toString() +UnflaggedApi: android.service.rotationresolver.RotationResolutionRequest#toString(): + New API must be flagged with @FlaggedApi: method android.service.rotationresolver.RotationResolutionRequest.toString() +UnflaggedApi: android.service.search.SearchUiService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.search.SearchUiService.onCreate() +UnflaggedApi: android.service.smartspace.SmartspaceService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.smartspace.SmartspaceService.onCreate() +UnflaggedApi: android.service.textclassifier.TextClassifierService#onUnbind(android.content.Intent): + New API must be flagged with @FlaggedApi: method android.service.textclassifier.TextClassifierService.onUnbind(android.content.Intent) +UnflaggedApi: android.service.timezone.TimeZoneProviderStatus#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.timezone.TimeZoneProviderStatus.equals(Object) +UnflaggedApi: android.service.timezone.TimeZoneProviderStatus#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.timezone.TimeZoneProviderStatus.hashCode() +UnflaggedApi: android.service.timezone.TimeZoneProviderStatus#toString(): + New API must be flagged with @FlaggedApi: method android.service.timezone.TimeZoneProviderStatus.toString() +UnflaggedApi: android.service.timezone.TimeZoneProviderSuggestion#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.timezone.TimeZoneProviderSuggestion.equals(Object) +UnflaggedApi: android.service.timezone.TimeZoneProviderSuggestion#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.timezone.TimeZoneProviderSuggestion.hashCode() +UnflaggedApi: android.service.timezone.TimeZoneProviderSuggestion#toString(): + New API must be flagged with @FlaggedApi: method android.service.timezone.TimeZoneProviderSuggestion.toString() +UnflaggedApi: android.service.translation.TranslationService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.translation.TranslationService.onCreate() +UnflaggedApi: android.service.trust.TrustAgentService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.trust.TrustAgentService.onCreate() +UnflaggedApi: android.service.voice.AlwaysOnHotwordDetector#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.voice.AlwaysOnHotwordDetector.equals(Object) +UnflaggedApi: android.service.voice.AlwaysOnHotwordDetector#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.voice.AlwaysOnHotwordDetector.hashCode() +UnflaggedApi: android.service.voice.AlwaysOnHotwordDetector.ModelParamRange#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.voice.AlwaysOnHotwordDetector.ModelParamRange.equals(Object) +UnflaggedApi: android.service.voice.AlwaysOnHotwordDetector.ModelParamRange#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.voice.AlwaysOnHotwordDetector.ModelParamRange.hashCode() +UnflaggedApi: android.service.voice.AlwaysOnHotwordDetector.ModelParamRange#toString(): + New API must be flagged with @FlaggedApi: method android.service.voice.AlwaysOnHotwordDetector.ModelParamRange.toString() +UnflaggedApi: android.service.voice.HotwordAudioStream#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordAudioStream.equals(Object) +UnflaggedApi: android.service.voice.HotwordAudioStream#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordAudioStream.hashCode() +UnflaggedApi: android.service.voice.HotwordAudioStream#toString(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordAudioStream.toString() +UnflaggedApi: android.service.voice.HotwordDetectedResult#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordDetectedResult.equals(Object) +UnflaggedApi: android.service.voice.HotwordDetectedResult#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordDetectedResult.hashCode() +UnflaggedApi: android.service.voice.HotwordDetectedResult#toString(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordDetectedResult.toString() +UnflaggedApi: android.service.voice.HotwordDetectionService#getSystemService(String): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordDetectionService.getSystemService(String) +UnflaggedApi: android.service.voice.HotwordDetectionServiceFailure#toString(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordDetectionServiceFailure.toString() +UnflaggedApi: android.service.voice.HotwordRejectedResult#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordRejectedResult.equals(Object) +UnflaggedApi: android.service.voice.HotwordRejectedResult#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordRejectedResult.hashCode() +UnflaggedApi: android.service.voice.HotwordRejectedResult#toString(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordRejectedResult.toString() +UnflaggedApi: android.service.voice.HotwordTrainingAudio: + New API must be flagged with @FlaggedApi: class android.service.voice.HotwordTrainingAudio +UnflaggedApi: android.service.voice.HotwordTrainingAudio#CONTENTS_FILE_DESCRIPTOR: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingAudio.CONTENTS_FILE_DESCRIPTOR +UnflaggedApi: android.service.voice.HotwordTrainingAudio#CREATOR: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingAudio.CREATOR +UnflaggedApi: android.service.voice.HotwordTrainingAudio#HOTWORD_OFFSET_UNSET: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingAudio.HOTWORD_OFFSET_UNSET +UnflaggedApi: android.service.voice.HotwordTrainingAudio#PARCELABLE_WRITE_RETURN_VALUE: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingAudio.PARCELABLE_WRITE_RETURN_VALUE +UnflaggedApi: android.service.voice.HotwordTrainingAudio#describeContents(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.describeContents() +UnflaggedApi: android.service.voice.HotwordTrainingAudio#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.equals(Object) +UnflaggedApi: android.service.voice.HotwordTrainingAudio#getAudioFormat(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.getAudioFormat() +UnflaggedApi: android.service.voice.HotwordTrainingAudio#getAudioType(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.getAudioType() +UnflaggedApi: android.service.voice.HotwordTrainingAudio#getHotwordAudio(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.getHotwordAudio() +UnflaggedApi: android.service.voice.HotwordTrainingAudio#getHotwordOffsetMillis(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.getHotwordOffsetMillis() +UnflaggedApi: android.service.voice.HotwordTrainingAudio#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.hashCode() +UnflaggedApi: android.service.voice.HotwordTrainingAudio#toString(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.toString() +UnflaggedApi: android.service.voice.HotwordTrainingAudio#writeToParcel(android.os.Parcel, int): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.writeToParcel(android.os.Parcel,int) +UnflaggedApi: android.service.voice.HotwordTrainingAudio.Builder: + New API must be flagged with @FlaggedApi: class android.service.voice.HotwordTrainingAudio.Builder +UnflaggedApi: android.service.voice.HotwordTrainingAudio.Builder#Builder(byte[], android.media.AudioFormat): + New API must be flagged with @FlaggedApi: constructor android.service.voice.HotwordTrainingAudio.Builder(byte[],android.media.AudioFormat) +UnflaggedApi: android.service.voice.HotwordTrainingAudio.Builder#build(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.Builder.build() +UnflaggedApi: android.service.voice.HotwordTrainingAudio.Builder#setAudioFormat(android.media.AudioFormat): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.Builder.setAudioFormat(android.media.AudioFormat) +UnflaggedApi: android.service.voice.HotwordTrainingAudio.Builder#setAudioType(int): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.Builder.setAudioType(int) +UnflaggedApi: android.service.voice.HotwordTrainingAudio.Builder#setHotwordAudio(byte...): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.Builder.setHotwordAudio(byte...) +UnflaggedApi: android.service.voice.HotwordTrainingAudio.Builder#setHotwordOffsetMillis(int): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingAudio.Builder.setHotwordOffsetMillis(int) +UnflaggedApi: android.service.voice.HotwordTrainingData: + New API must be flagged with @FlaggedApi: class android.service.voice.HotwordTrainingData +UnflaggedApi: android.service.voice.HotwordTrainingData#CONTENTS_FILE_DESCRIPTOR: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingData.CONTENTS_FILE_DESCRIPTOR +UnflaggedApi: android.service.voice.HotwordTrainingData#CREATOR: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingData.CREATOR +UnflaggedApi: android.service.voice.HotwordTrainingData#PARCELABLE_WRITE_RETURN_VALUE: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingData.PARCELABLE_WRITE_RETURN_VALUE +UnflaggedApi: android.service.voice.HotwordTrainingData#TIMEOUT_STAGE_EARLY: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingData.TIMEOUT_STAGE_EARLY +UnflaggedApi: android.service.voice.HotwordTrainingData#TIMEOUT_STAGE_LATE: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingData.TIMEOUT_STAGE_LATE +UnflaggedApi: android.service.voice.HotwordTrainingData#TIMEOUT_STAGE_MIDDLE: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingData.TIMEOUT_STAGE_MIDDLE +UnflaggedApi: android.service.voice.HotwordTrainingData#TIMEOUT_STAGE_UNKNOWN: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingData.TIMEOUT_STAGE_UNKNOWN +UnflaggedApi: android.service.voice.HotwordTrainingData#TIMEOUT_STAGE_VERY_EARLY: + New API must be flagged with @FlaggedApi: field android.service.voice.HotwordTrainingData.TIMEOUT_STAGE_VERY_EARLY +UnflaggedApi: android.service.voice.HotwordTrainingData#describeContents(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.describeContents() +UnflaggedApi: android.service.voice.HotwordTrainingData#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.equals(Object) +UnflaggedApi: android.service.voice.HotwordTrainingData#getMaxTrainingDataSize(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.getMaxTrainingDataSize() +UnflaggedApi: android.service.voice.HotwordTrainingData#getTimeoutStage(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.getTimeoutStage() +UnflaggedApi: android.service.voice.HotwordTrainingData#getTrainingAudios(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.getTrainingAudios() +UnflaggedApi: android.service.voice.HotwordTrainingData#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.hashCode() +UnflaggedApi: android.service.voice.HotwordTrainingData#toString(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.toString() +UnflaggedApi: android.service.voice.HotwordTrainingData#writeToParcel(android.os.Parcel, int): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.writeToParcel(android.os.Parcel,int) +UnflaggedApi: android.service.voice.HotwordTrainingData.Builder: + New API must be flagged with @FlaggedApi: class android.service.voice.HotwordTrainingData.Builder +UnflaggedApi: android.service.voice.HotwordTrainingData.Builder#Builder(): + New API must be flagged with @FlaggedApi: constructor android.service.voice.HotwordTrainingData.Builder() +UnflaggedApi: android.service.voice.HotwordTrainingData.Builder#addTrainingAudio(android.service.voice.HotwordTrainingAudio): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.Builder.addTrainingAudio(android.service.voice.HotwordTrainingAudio) +UnflaggedApi: android.service.voice.HotwordTrainingData.Builder#build(): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.Builder.build() +UnflaggedApi: android.service.voice.HotwordTrainingData.Builder#setTimeoutStage(int): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.Builder.setTimeoutStage(int) +UnflaggedApi: android.service.voice.HotwordTrainingData.Builder#setTrainingAudios(java.util.List<android.service.voice.HotwordTrainingAudio>): + New API must be flagged with @FlaggedApi: method android.service.voice.HotwordTrainingData.Builder.setTrainingAudios(java.util.List<android.service.voice.HotwordTrainingAudio>) +UnflaggedApi: android.service.voice.SoundTriggerFailure#toString(): + New API must be flagged with @FlaggedApi: method android.service.voice.SoundTriggerFailure.toString() +UnflaggedApi: android.service.voice.VisualQueryDetectionService#getSystemService(String): + New API must be flagged with @FlaggedApi: method android.service.voice.VisualQueryDetectionService.getSystemService(String) +UnflaggedApi: android.service.voice.VisualQueryDetectionService#openFileInput(String): + New API must be flagged with @FlaggedApi: method android.service.voice.VisualQueryDetectionService.openFileInput(String) +UnflaggedApi: android.service.voice.VisualQueryDetectionServiceFailure#toString(): + New API must be flagged with @FlaggedApi: method android.service.voice.VisualQueryDetectionServiceFailure.toString() +UnflaggedApi: android.service.wallpaper.WallpaperService.Engine#isInAmbientMode(): + New API must be flagged with @FlaggedApi: method android.service.wallpaper.WallpaperService.Engine.isInAmbientMode() +UnflaggedApi: android.service.wallpaper.WallpaperService.Engine#onAmbientModeChanged(boolean, long): + New API must be flagged with @FlaggedApi: method android.service.wallpaper.WallpaperService.Engine.onAmbientModeChanged(boolean,long) +UnflaggedApi: android.service.wallpapereffectsgeneration.WallpaperEffectsGenerationService#onCreate(): + New API must be flagged with @FlaggedApi: method android.service.wallpapereffectsgeneration.WallpaperEffectsGenerationService.onCreate() +UnflaggedApi: android.service.watchdog.ExplicitHealthCheckService.PackageConfig#equals(Object): + New API must be flagged with @FlaggedApi: method android.service.watchdog.ExplicitHealthCheckService.PackageConfig.equals(Object) +UnflaggedApi: android.service.watchdog.ExplicitHealthCheckService.PackageConfig#hashCode(): + New API must be flagged with @FlaggedApi: method android.service.watchdog.ExplicitHealthCheckService.PackageConfig.hashCode() +UnflaggedApi: android.service.watchdog.ExplicitHealthCheckService.PackageConfig#toString(): + New API must be flagged with @FlaggedApi: method android.service.watchdog.ExplicitHealthCheckService.PackageConfig.toString() +UnflaggedApi: android.telecom.AudioState#equals(Object): + New API must be flagged with @FlaggedApi: method android.telecom.AudioState.equals(Object) +UnflaggedApi: android.telecom.AudioState#toString(): + New API must be flagged with @FlaggedApi: method android.telecom.AudioState.toString() +UnflaggedApi: android.telecom.BluetoothCallQualityReport#equals(Object): + New API must be flagged with @FlaggedApi: method android.telecom.BluetoothCallQualityReport.equals(Object) +UnflaggedApi: android.telecom.BluetoothCallQualityReport#hashCode(): + New API must be flagged with @FlaggedApi: method android.telecom.BluetoothCallQualityReport.hashCode() +UnflaggedApi: android.telecom.CallScreeningService.CallResponse.Builder#setShouldScreenCallViaAudioProcessing(boolean): + New API must be flagged with @FlaggedApi: method android.telecom.CallScreeningService.CallResponse.Builder.setShouldScreenCallViaAudioProcessing(boolean) +UnflaggedApi: android.telecom.Connection.CallFilteringCompletionInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telecom.Connection.CallFilteringCompletionInfo.toString() +UnflaggedApi: android.telecom.StreamingCall#EXTRA_CALL_ID: + New API must be flagged with @FlaggedApi: field android.telecom.StreamingCall.EXTRA_CALL_ID +UnflaggedApi: android.telephony.CallAttributes#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.CallAttributes.equals(Object) +UnflaggedApi: android.telephony.CallAttributes#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.CallAttributes.hashCode() +UnflaggedApi: android.telephony.CallAttributes#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.CallAttributes.toString() +UnflaggedApi: android.telephony.CallQuality#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.CallQuality.equals(Object) +UnflaggedApi: android.telephony.CallQuality#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.CallQuality.hashCode() +UnflaggedApi: android.telephony.CallQuality#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.CallQuality.toString() +UnflaggedApi: android.telephony.CallState#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.CallState.equals(Object) +UnflaggedApi: android.telephony.CallState#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.CallState.hashCode() +UnflaggedApi: android.telephony.CallState#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.CallState.toString() +UnflaggedApi: android.telephony.CarrierRestrictionRules#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.CarrierRestrictionRules.toString() +UnflaggedApi: android.telephony.CbGeoUtils.Circle#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.CbGeoUtils.Circle.toString() +UnflaggedApi: android.telephony.CbGeoUtils.LatLng#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.CbGeoUtils.LatLng.toString() +UnflaggedApi: android.telephony.CbGeoUtils.Polygon#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.CbGeoUtils.Polygon.toString() +UnflaggedApi: android.telephony.CellBroadcastIdRange#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.CellBroadcastIdRange.equals(Object) +UnflaggedApi: android.telephony.CellBroadcastIdRange#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.CellBroadcastIdRange.hashCode() +UnflaggedApi: android.telephony.CellBroadcastIdRange#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.CellBroadcastIdRange.toString() +UnflaggedApi: android.telephony.DataSpecificRegistrationInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.DataSpecificRegistrationInfo.equals(Object) +UnflaggedApi: android.telephony.DataSpecificRegistrationInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.DataSpecificRegistrationInfo.hashCode() +UnflaggedApi: android.telephony.DataSpecificRegistrationInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.DataSpecificRegistrationInfo.toString() +UnflaggedApi: android.telephony.DataThrottlingRequest#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.DataThrottlingRequest.toString() +UnflaggedApi: android.telephony.ImsiEncryptionInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ImsiEncryptionInfo.toString() +UnflaggedApi: android.telephony.LinkCapacityEstimate#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.LinkCapacityEstimate.equals(Object) +UnflaggedApi: android.telephony.LinkCapacityEstimate#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.LinkCapacityEstimate.hashCode() +UnflaggedApi: android.telephony.LinkCapacityEstimate#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.LinkCapacityEstimate.toString() +UnflaggedApi: android.telephony.LteVopsSupportInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.LteVopsSupportInfo.toString() +UnflaggedApi: android.telephony.ModemActivityInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ModemActivityInfo.equals(Object) +UnflaggedApi: android.telephony.ModemActivityInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ModemActivityInfo.hashCode() +UnflaggedApi: android.telephony.ModemActivityInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ModemActivityInfo.toString() +UnflaggedApi: android.telephony.NetworkRegistrationInfo.Builder#setIsNonTerrestrialNetwork(boolean): + New API must be flagged with @FlaggedApi: method android.telephony.NetworkRegistrationInfo.Builder.setIsNonTerrestrialNetwork(boolean) +UnflaggedApi: android.telephony.NetworkService#onUnbind(android.content.Intent): + New API must be flagged with @FlaggedApi: method android.telephony.NetworkService.onUnbind(android.content.Intent) +UnflaggedApi: android.telephony.NrVopsSupportInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.NrVopsSupportInfo.toString() +UnflaggedApi: android.telephony.PhoneCapability#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.PhoneCapability.equals(Object) +UnflaggedApi: android.telephony.PhoneCapability#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.PhoneCapability.hashCode() +UnflaggedApi: android.telephony.PhoneCapability#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.PhoneCapability.toString() +UnflaggedApi: android.telephony.PhoneNumberRange#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.PhoneNumberRange.equals(Object) +UnflaggedApi: android.telephony.PhoneNumberRange#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.PhoneNumberRange.hashCode() +UnflaggedApi: android.telephony.PhoneNumberRange#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.PhoneNumberRange.toString() +UnflaggedApi: android.telephony.PinResult#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.PinResult.equals(Object) +UnflaggedApi: android.telephony.PinResult#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.PinResult.hashCode() +UnflaggedApi: android.telephony.PinResult#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.PinResult.toString() +UnflaggedApi: android.telephony.PreciseCallState#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.PreciseCallState.equals(Object) +UnflaggedApi: android.telephony.PreciseCallState#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.PreciseCallState.hashCode() +UnflaggedApi: android.telephony.PreciseCallState#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.PreciseCallState.toString() +UnflaggedApi: android.telephony.SmsCbCmasInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.SmsCbCmasInfo.toString() +UnflaggedApi: android.telephony.SmsCbEtwsInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.SmsCbEtwsInfo.toString() +UnflaggedApi: android.telephony.SmsCbLocation#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.SmsCbLocation.equals(Object) +UnflaggedApi: android.telephony.SmsCbLocation#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.SmsCbLocation.hashCode() +UnflaggedApi: android.telephony.SmsCbLocation#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.SmsCbLocation.toString() +UnflaggedApi: android.telephony.SmsCbMessage#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.SmsCbMessage.toString() +UnflaggedApi: android.telephony.TelephonyHistogram#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.TelephonyHistogram.toString() +UnflaggedApi: android.telephony.TelephonyManager.ModemActivityInfoException#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.TelephonyManager.ModemActivityInfoException.toString() +UnflaggedApi: android.telephony.ThermalMitigationRequest#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ThermalMitigationRequest.toString() +UnflaggedApi: android.telephony.UiccAccessRule#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.UiccAccessRule.equals(Object) +UnflaggedApi: android.telephony.UiccAccessRule#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.UiccAccessRule.hashCode() +UnflaggedApi: android.telephony.UiccAccessRule#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.UiccAccessRule.toString() +UnflaggedApi: android.telephony.UiccSlotInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.UiccSlotInfo.equals(Object) +UnflaggedApi: android.telephony.UiccSlotInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.UiccSlotInfo.hashCode() +UnflaggedApi: android.telephony.UiccSlotInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.UiccSlotInfo.toString() +UnflaggedApi: android.telephony.UiccSlotMapping#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.UiccSlotMapping.equals(Object) +UnflaggedApi: android.telephony.UiccSlotMapping#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.UiccSlotMapping.hashCode() +UnflaggedApi: android.telephony.UiccSlotMapping#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.UiccSlotMapping.toString() +UnflaggedApi: android.telephony.VopsSupportInfo#writeToParcel(android.os.Parcel, int): + New API must be flagged with @FlaggedApi: method android.telephony.VopsSupportInfo.writeToParcel(android.os.Parcel,int) +UnflaggedApi: android.telephony.cdma.CdmaSmsCbProgramData#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.cdma.CdmaSmsCbProgramData.toString() +UnflaggedApi: android.telephony.data.DataCallResponse#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.data.DataCallResponse.equals(Object) +UnflaggedApi: android.telephony.data.DataCallResponse#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.data.DataCallResponse.hashCode() +UnflaggedApi: android.telephony.data.DataCallResponse#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.data.DataCallResponse.toString() +UnflaggedApi: android.telephony.data.DataProfile#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.data.DataProfile.equals(Object) +UnflaggedApi: android.telephony.data.DataProfile#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.data.DataProfile.hashCode() +UnflaggedApi: android.telephony.data.DataProfile#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.data.DataProfile.toString() +UnflaggedApi: android.telephony.data.DataService#onDestroy(): + New API must be flagged with @FlaggedApi: method android.telephony.data.DataService.onDestroy() +UnflaggedApi: android.telephony.data.DataService#onUnbind(android.content.Intent): + New API must be flagged with @FlaggedApi: method android.telephony.data.DataService.onUnbind(android.content.Intent) +UnflaggedApi: android.telephony.data.EpsBearerQosSessionAttributes#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.data.EpsBearerQosSessionAttributes.equals(Object) +UnflaggedApi: android.telephony.data.EpsBearerQosSessionAttributes#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.data.EpsBearerQosSessionAttributes.hashCode() +UnflaggedApi: android.telephony.data.NrQosSessionAttributes#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.data.NrQosSessionAttributes.equals(Object) +UnflaggedApi: android.telephony.data.NrQosSessionAttributes#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.data.NrQosSessionAttributes.hashCode() +UnflaggedApi: android.telephony.data.ThrottleStatus#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.data.ThrottleStatus.equals(Object) +UnflaggedApi: android.telephony.data.ThrottleStatus#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.data.ThrottleStatus.hashCode() +UnflaggedApi: android.telephony.data.ThrottleStatus#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.data.ThrottleStatus.toString() +UnflaggedApi: android.telephony.euicc.EuiccNotification#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.euicc.EuiccNotification.equals(Object) +UnflaggedApi: android.telephony.euicc.EuiccNotification#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.euicc.EuiccNotification.hashCode() +UnflaggedApi: android.telephony.euicc.EuiccNotification#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.euicc.EuiccNotification.toString() +UnflaggedApi: android.telephony.euicc.EuiccRulesAuthTable#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.euicc.EuiccRulesAuthTable.equals(Object) +UnflaggedApi: android.telephony.gba.UaSecurityProtocolIdentifier#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.gba.UaSecurityProtocolIdentifier.equals(Object) +UnflaggedApi: android.telephony.gba.UaSecurityProtocolIdentifier#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.gba.UaSecurityProtocolIdentifier.hashCode() +UnflaggedApi: android.telephony.gba.UaSecurityProtocolIdentifier#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.gba.UaSecurityProtocolIdentifier.toString() +UnflaggedApi: android.telephony.ims.AudioCodecAttributes#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.AudioCodecAttributes.toString() +UnflaggedApi: android.telephony.ims.DelegateRegistrationState#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.DelegateRegistrationState.equals(Object) +UnflaggedApi: android.telephony.ims.DelegateRegistrationState#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.DelegateRegistrationState.hashCode() +UnflaggedApi: android.telephony.ims.DelegateRegistrationState#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.DelegateRegistrationState.toString() +UnflaggedApi: android.telephony.ims.DelegateRequest#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.DelegateRequest.equals(Object) +UnflaggedApi: android.telephony.ims.DelegateRequest#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.DelegateRequest.hashCode() +UnflaggedApi: android.telephony.ims.DelegateRequest#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.DelegateRequest.toString() +UnflaggedApi: android.telephony.ims.FeatureTagState#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.FeatureTagState.equals(Object) +UnflaggedApi: android.telephony.ims.FeatureTagState#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.FeatureTagState.hashCode() +UnflaggedApi: android.telephony.ims.FeatureTagState#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.FeatureTagState.toString() +UnflaggedApi: android.telephony.ims.ImsCallForwardInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.ImsCallForwardInfo.toString() +UnflaggedApi: android.telephony.ims.ImsCallProfile#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.ImsCallProfile.toString() +UnflaggedApi: android.telephony.ims.ImsConferenceState#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.ImsConferenceState.toString() +UnflaggedApi: android.telephony.ims.ImsExternalCallState#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.ImsExternalCallState.toString() +UnflaggedApi: android.telephony.ims.ImsMmTelManager.RegistrationCallback#onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo): + New API must be flagged with @FlaggedApi: method android.telephony.ims.ImsMmTelManager.RegistrationCallback.onTechnologyChangeFailed(int,android.telephony.ims.ImsReasonInfo) +UnflaggedApi: android.telephony.ims.ImsMmTelManager.RegistrationCallback#onUnregistered(android.telephony.ims.ImsReasonInfo): + New API must be flagged with @FlaggedApi: method android.telephony.ims.ImsMmTelManager.RegistrationCallback.onUnregistered(android.telephony.ims.ImsReasonInfo) +UnflaggedApi: android.telephony.ims.ImsSsData#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.ImsSsData.toString() +UnflaggedApi: android.telephony.ims.ImsSsInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.ImsSsInfo.toString() +UnflaggedApi: android.telephony.ims.ImsStreamMediaProfile#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.ImsStreamMediaProfile.toString() +UnflaggedApi: android.telephony.ims.ImsSuppServiceNotification#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.ImsSuppServiceNotification.toString() +UnflaggedApi: android.telephony.ims.MediaQualityStatus#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.MediaQualityStatus.equals(Object) +UnflaggedApi: android.telephony.ims.MediaQualityStatus#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.MediaQualityStatus.hashCode() +UnflaggedApi: android.telephony.ims.MediaQualityStatus#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.MediaQualityStatus.toString() +UnflaggedApi: android.telephony.ims.MediaThreshold#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.MediaThreshold.equals(Object) +UnflaggedApi: android.telephony.ims.MediaThreshold#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.MediaThreshold.hashCode() +UnflaggedApi: android.telephony.ims.MediaThreshold#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.MediaThreshold.toString() +UnflaggedApi: android.telephony.ims.PublishAttributes#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.PublishAttributes.equals(Object) +UnflaggedApi: android.telephony.ims.PublishAttributes#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.PublishAttributes.hashCode() +UnflaggedApi: android.telephony.ims.PublishAttributes#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.PublishAttributes.toString() +UnflaggedApi: android.telephony.ims.RcsClientConfiguration#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.RcsClientConfiguration.equals(Object) +UnflaggedApi: android.telephony.ims.RcsClientConfiguration#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.RcsClientConfiguration.hashCode() +UnflaggedApi: android.telephony.ims.RcsContactPresenceTuple#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.RcsContactPresenceTuple.toString() +UnflaggedApi: android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities.toString() +UnflaggedApi: android.telephony.ims.RcsContactUceCapability#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.RcsContactUceCapability.toString() +UnflaggedApi: android.telephony.ims.RtpHeaderExtension#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.RtpHeaderExtension.equals(Object) +UnflaggedApi: android.telephony.ims.RtpHeaderExtension#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.RtpHeaderExtension.hashCode() +UnflaggedApi: android.telephony.ims.RtpHeaderExtension#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.RtpHeaderExtension.toString() +UnflaggedApi: android.telephony.ims.RtpHeaderExtensionType#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.RtpHeaderExtensionType.equals(Object) +UnflaggedApi: android.telephony.ims.RtpHeaderExtensionType#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.RtpHeaderExtensionType.hashCode() +UnflaggedApi: android.telephony.ims.RtpHeaderExtensionType#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.RtpHeaderExtensionType.toString() +UnflaggedApi: android.telephony.ims.SipDelegateConfiguration#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SipDelegateConfiguration.equals(Object) +UnflaggedApi: android.telephony.ims.SipDelegateConfiguration#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SipDelegateConfiguration.hashCode() +UnflaggedApi: android.telephony.ims.SipDelegateConfiguration#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SipDelegateConfiguration.toString() +UnflaggedApi: android.telephony.ims.SipDelegateConfiguration.IpSecConfiguration#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SipDelegateConfiguration.IpSecConfiguration.equals(Object) +UnflaggedApi: android.telephony.ims.SipDelegateConfiguration.IpSecConfiguration#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SipDelegateConfiguration.IpSecConfiguration.hashCode() +UnflaggedApi: android.telephony.ims.SipDelegateConfiguration.IpSecConfiguration#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SipDelegateConfiguration.IpSecConfiguration.toString() +UnflaggedApi: android.telephony.ims.SipDialogState#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SipDialogState.equals(Object) +UnflaggedApi: android.telephony.ims.SipDialogState#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SipDialogState.hashCode() +UnflaggedApi: android.telephony.ims.SipMessage#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SipMessage.equals(Object) +UnflaggedApi: android.telephony.ims.SipMessage#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SipMessage.hashCode() +UnflaggedApi: android.telephony.ims.SipMessage#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SipMessage.toString() +UnflaggedApi: android.telephony.ims.SrvccCall#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SrvccCall.equals(Object) +UnflaggedApi: android.telephony.ims.SrvccCall#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SrvccCall.hashCode() +UnflaggedApi: android.telephony.ims.SrvccCall#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.SrvccCall.toString() +UnflaggedApi: android.telephony.ims.feature.CapabilityChangeRequest#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.feature.CapabilityChangeRequest.toString() +UnflaggedApi: android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.feature.CapabilityChangeRequest.CapabilityPair.toString() +UnflaggedApi: android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair.equals(Object) +UnflaggedApi: android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair.hashCode() +UnflaggedApi: android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.ims.stub.ImsFeatureConfiguration.FeatureSlotPair.toString() +UnflaggedApi: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String): + New API must be flagged with @FlaggedApi: method android.telephony.mbms.DownloadRequest.Builder.setServiceId(String) +UnflaggedApi: android.telephony.mbms.vendor.MbmsDownloadServiceBase#DESCRIPTOR: + New API must be flagged with @FlaggedApi: field android.telephony.mbms.vendor.MbmsDownloadServiceBase.DESCRIPTOR +UnflaggedApi: android.telephony.mbms.vendor.MbmsStreamingServiceBase#DESCRIPTOR: + New API must be flagged with @FlaggedApi: field android.telephony.mbms.vendor.MbmsStreamingServiceBase.DESCRIPTOR +UnflaggedApi: android.telephony.satellite.AntennaDirection: + New API must be flagged with @FlaggedApi: class android.telephony.satellite.AntennaDirection +UnflaggedApi: android.telephony.satellite.AntennaDirection#CONTENTS_FILE_DESCRIPTOR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.AntennaDirection.CONTENTS_FILE_DESCRIPTOR +UnflaggedApi: android.telephony.satellite.AntennaDirection#CREATOR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.AntennaDirection.CREATOR +UnflaggedApi: android.telephony.satellite.AntennaDirection#PARCELABLE_WRITE_RETURN_VALUE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.AntennaDirection.PARCELABLE_WRITE_RETURN_VALUE +UnflaggedApi: android.telephony.satellite.AntennaDirection#describeContents(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaDirection.describeContents() +UnflaggedApi: android.telephony.satellite.AntennaDirection#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaDirection.equals(Object) +UnflaggedApi: android.telephony.satellite.AntennaDirection#getX(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaDirection.getX() +UnflaggedApi: android.telephony.satellite.AntennaDirection#getY(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaDirection.getY() +UnflaggedApi: android.telephony.satellite.AntennaDirection#getZ(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaDirection.getZ() +UnflaggedApi: android.telephony.satellite.AntennaDirection#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaDirection.hashCode() +UnflaggedApi: android.telephony.satellite.AntennaDirection#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaDirection.toString() +UnflaggedApi: android.telephony.satellite.AntennaDirection#writeToParcel(android.os.Parcel, int): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaDirection.writeToParcel(android.os.Parcel,int) +UnflaggedApi: android.telephony.satellite.AntennaPosition: + New API must be flagged with @FlaggedApi: class android.telephony.satellite.AntennaPosition +UnflaggedApi: android.telephony.satellite.AntennaPosition#CONTENTS_FILE_DESCRIPTOR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.AntennaPosition.CONTENTS_FILE_DESCRIPTOR +UnflaggedApi: android.telephony.satellite.AntennaPosition#CREATOR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.AntennaPosition.CREATOR +UnflaggedApi: android.telephony.satellite.AntennaPosition#PARCELABLE_WRITE_RETURN_VALUE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.AntennaPosition.PARCELABLE_WRITE_RETURN_VALUE +UnflaggedApi: android.telephony.satellite.AntennaPosition#describeContents(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaPosition.describeContents() +UnflaggedApi: android.telephony.satellite.AntennaPosition#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaPosition.equals(Object) +UnflaggedApi: android.telephony.satellite.AntennaPosition#getAntennaDirection(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaPosition.getAntennaDirection() +UnflaggedApi: android.telephony.satellite.AntennaPosition#getSuggestedHoldPosition(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaPosition.getSuggestedHoldPosition() +UnflaggedApi: android.telephony.satellite.AntennaPosition#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaPosition.hashCode() +UnflaggedApi: android.telephony.satellite.AntennaPosition#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaPosition.toString() +UnflaggedApi: android.telephony.satellite.AntennaPosition#writeToParcel(android.os.Parcel, int): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.AntennaPosition.writeToParcel(android.os.Parcel,int) +UnflaggedApi: android.telephony.satellite.PointingInfo: + New API must be flagged with @FlaggedApi: class android.telephony.satellite.PointingInfo +UnflaggedApi: android.telephony.satellite.PointingInfo#CONTENTS_FILE_DESCRIPTOR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.PointingInfo.CONTENTS_FILE_DESCRIPTOR +UnflaggedApi: android.telephony.satellite.PointingInfo#CREATOR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.PointingInfo.CREATOR +UnflaggedApi: android.telephony.satellite.PointingInfo#PARCELABLE_WRITE_RETURN_VALUE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.PointingInfo.PARCELABLE_WRITE_RETURN_VALUE +UnflaggedApi: android.telephony.satellite.PointingInfo#describeContents(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.PointingInfo.describeContents() +UnflaggedApi: android.telephony.satellite.PointingInfo#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.PointingInfo.equals(Object) +UnflaggedApi: android.telephony.satellite.PointingInfo#getSatelliteAzimuthDegrees(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.PointingInfo.getSatelliteAzimuthDegrees() +UnflaggedApi: android.telephony.satellite.PointingInfo#getSatelliteElevationDegrees(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.PointingInfo.getSatelliteElevationDegrees() +UnflaggedApi: android.telephony.satellite.PointingInfo#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.PointingInfo.hashCode() +UnflaggedApi: android.telephony.satellite.PointingInfo#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.PointingInfo.toString() +UnflaggedApi: android.telephony.satellite.PointingInfo#writeToParcel(android.os.Parcel, int): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.PointingInfo.writeToParcel(android.os.Parcel,int) +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities: + New API must be flagged with @FlaggedApi: class android.telephony.satellite.SatelliteCapabilities +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#CONTENTS_FILE_DESCRIPTOR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteCapabilities.CONTENTS_FILE_DESCRIPTOR +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#CREATOR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteCapabilities.CREATOR +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#PARCELABLE_WRITE_RETURN_VALUE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteCapabilities.PARCELABLE_WRITE_RETURN_VALUE +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#describeContents(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteCapabilities.describeContents() +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#equals(Object): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteCapabilities.equals(Object) +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#getAntennaPositionMap(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteCapabilities.getAntennaPositionMap() +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#getMaxBytesPerOutgoingDatagram(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteCapabilities.getMaxBytesPerOutgoingDatagram() +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#getSupportedRadioTechnologies(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteCapabilities.getSupportedRadioTechnologies() +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#hashCode(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteCapabilities.hashCode() +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#isPointingRequired(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteCapabilities.isPointingRequired() +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#toString(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteCapabilities.toString() +UnflaggedApi: android.telephony.satellite.SatelliteCapabilities#writeToParcel(android.os.Parcel, int): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteCapabilities.writeToParcel(android.os.Parcel,int) +UnflaggedApi: android.telephony.satellite.SatelliteDatagram: + New API must be flagged with @FlaggedApi: class android.telephony.satellite.SatelliteDatagram +UnflaggedApi: android.telephony.satellite.SatelliteDatagram#CONTENTS_FILE_DESCRIPTOR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteDatagram.CONTENTS_FILE_DESCRIPTOR +UnflaggedApi: android.telephony.satellite.SatelliteDatagram#CREATOR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteDatagram.CREATOR +UnflaggedApi: android.telephony.satellite.SatelliteDatagram#PARCELABLE_WRITE_RETURN_VALUE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteDatagram.PARCELABLE_WRITE_RETURN_VALUE +UnflaggedApi: android.telephony.satellite.SatelliteDatagram#describeContents(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteDatagram.describeContents() +UnflaggedApi: android.telephony.satellite.SatelliteDatagram#getSatelliteDatagram(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteDatagram.getSatelliteDatagram() +UnflaggedApi: android.telephony.satellite.SatelliteDatagram#writeToParcel(android.os.Parcel, int): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteDatagram.writeToParcel(android.os.Parcel,int) +UnflaggedApi: android.telephony.satellite.SatelliteDatagramCallback: + New API must be flagged with @FlaggedApi: class android.telephony.satellite.SatelliteDatagramCallback +UnflaggedApi: android.telephony.satellite.SatelliteDatagramCallback#onSatelliteDatagramReceived(long, android.telephony.satellite.SatelliteDatagram, int, java.util.function.Consumer<java.lang.Void>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteDatagramCallback.onSatelliteDatagramReceived(long,android.telephony.satellite.SatelliteDatagram,int,java.util.function.Consumer<java.lang.Void>) +UnflaggedApi: android.telephony.satellite.SatelliteManager: + New API must be flagged with @FlaggedApi: class android.telephony.satellite.SatelliteManager +UnflaggedApi: android.telephony.satellite.SatelliteManager#DATAGRAM_TYPE_LOCATION_SHARING: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_LOCATION_SHARING +UnflaggedApi: android.telephony.satellite.SatelliteManager#DATAGRAM_TYPE_SOS_MESSAGE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_SOS_MESSAGE +UnflaggedApi: android.telephony.satellite.SatelliteManager#DATAGRAM_TYPE_UNKNOWN: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.DATAGRAM_TYPE_UNKNOWN +UnflaggedApi: android.telephony.satellite.SatelliteManager#DEVICE_HOLD_POSITION_LANDSCAPE_LEFT: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.DEVICE_HOLD_POSITION_LANDSCAPE_LEFT +UnflaggedApi: android.telephony.satellite.SatelliteManager#DEVICE_HOLD_POSITION_LANDSCAPE_RIGHT: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.DEVICE_HOLD_POSITION_LANDSCAPE_RIGHT +UnflaggedApi: android.telephony.satellite.SatelliteManager#DEVICE_HOLD_POSITION_PORTRAIT: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.DEVICE_HOLD_POSITION_PORTRAIT +UnflaggedApi: android.telephony.satellite.SatelliteManager#DEVICE_HOLD_POSITION_UNKNOWN: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.DEVICE_HOLD_POSITION_UNKNOWN +UnflaggedApi: android.telephony.satellite.SatelliteManager#DISPLAY_MODE_CLOSED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.DISPLAY_MODE_CLOSED +UnflaggedApi: android.telephony.satellite.SatelliteManager#DISPLAY_MODE_FIXED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.DISPLAY_MODE_FIXED +UnflaggedApi: android.telephony.satellite.SatelliteManager#DISPLAY_MODE_OPENED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.DISPLAY_MODE_OPENED +UnflaggedApi: android.telephony.satellite.SatelliteManager#DISPLAY_MODE_UNKNOWN: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.DISPLAY_MODE_UNKNOWN +UnflaggedApi: android.telephony.satellite.SatelliteManager#NT_RADIO_TECHNOLOGY_EMTC_NTN: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_EMTC_NTN +UnflaggedApi: android.telephony.satellite.SatelliteManager#NT_RADIO_TECHNOLOGY_NB_IOT_NTN: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_NB_IOT_NTN +UnflaggedApi: android.telephony.satellite.SatelliteManager#NT_RADIO_TECHNOLOGY_NR_NTN: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_NR_NTN +UnflaggedApi: android.telephony.satellite.SatelliteManager#NT_RADIO_TECHNOLOGY_PROPRIETARY: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_PROPRIETARY +UnflaggedApi: android.telephony.satellite.SatelliteManager#NT_RADIO_TECHNOLOGY_UNKNOWN: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.NT_RADIO_TECHNOLOGY_UNKNOWN +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_ACCESS_BARRED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_ACCESS_BARRED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_IDLE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_FAILED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_NONE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVE_SUCCESS +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SENDING +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_FAILED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_SEND_SUCCESS +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_ERROR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_ERROR +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_ERROR_NONE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_ERROR_NONE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_INVALID_ARGUMENTS: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_INVALID_ARGUMENTS +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_INVALID_MODEM_STATE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_INVALID_MODEM_STATE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_INVALID_TELEPHONY_STATE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_INVALID_TELEPHONY_STATE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_MODEM_BUSY: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_BUSY +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_MODEM_ERROR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_ERROR +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_MODEM_STATE_DATAGRAM_RETRYING: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_RETRYING +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_MODEM_STATE_IDLE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_IDLE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_MODEM_STATE_LISTENING: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_LISTENING +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_MODEM_STATE_OFF: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_OFF +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_MODEM_STATE_UNAVAILABLE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNAVAILABLE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_MODEM_STATE_UNKNOWN: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_MODEM_STATE_UNKNOWN +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_NETWORK_ERROR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_NETWORK_ERROR +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_NETWORK_TIMEOUT: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_NETWORK_TIMEOUT +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_NOT_AUTHORIZED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_NOT_AUTHORIZED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_NOT_REACHABLE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_NOT_REACHABLE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_NOT_SUPPORTED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_NOT_SUPPORTED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_NO_RESOURCES: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_NO_RESOURCES +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RADIO_NOT_AVAILABLE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RADIO_NOT_AVAILABLE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_REQUEST_ABORTED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_REQUEST_ABORTED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_REQUEST_FAILED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_REQUEST_FAILED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_REQUEST_IN_PROGRESS: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_REQUEST_IN_PROGRESS +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_REQUEST_NOT_SUPPORTED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_REQUEST_NOT_SUPPORTED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_ACCESS_BARRED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ACCESS_BARRED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_ERROR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_ERROR +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_INVALID_ARGUMENTS: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_ARGUMENTS +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_INVALID_MODEM_STATE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_MODEM_STATE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_INVALID_TELEPHONY_STATE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_INVALID_TELEPHONY_STATE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_MODEM_BUSY: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_BUSY +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_MODEM_ERROR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_MODEM_ERROR +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_NETWORK_ERROR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NETWORK_ERROR +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_NETWORK_TIMEOUT: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NETWORK_TIMEOUT +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_NOT_AUTHORIZED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_AUTHORIZED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_NOT_REACHABLE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_REACHABLE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_NOT_SUPPORTED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NOT_SUPPORTED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_NO_RESOURCES: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_NO_RESOURCES +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_RADIO_NOT_AVAILABLE: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_RADIO_NOT_AVAILABLE +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_REQUEST_ABORTED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_ABORTED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_REQUEST_FAILED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_FAILED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_REQUEST_IN_PROGRESS: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_IN_PROGRESS +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_REQUEST_NOT_SUPPORTED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_REQUEST_NOT_SUPPORTED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_SERVER_ERROR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVER_ERROR +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_SERVICE_ERROR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVICE_ERROR +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_SERVICE_NOT_PROVISIONED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVICE_NOT_PROVISIONED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SERVICE_PROVISION_IN_PROGRESS +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_RESULT_SUCCESS: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_RESULT_SUCCESS +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_SERVER_ERROR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_SERVER_ERROR +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_SERVICE_ERROR: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_SERVICE_ERROR +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_SERVICE_NOT_PROVISIONED: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_SERVICE_NOT_PROVISIONED +UnflaggedApi: android.telephony.satellite.SatelliteManager#SATELLITE_SERVICE_PROVISION_IN_PROGRESS: + New API must be flagged with @FlaggedApi: field android.telephony.satellite.SatelliteManager.SATELLITE_SERVICE_PROVISION_IN_PROGRESS +UnflaggedApi: android.telephony.satellite.SatelliteManager#deprovisionSatelliteService(String, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.deprovisionSatelliteService(String,java.util.concurrent.Executor,java.util.function.Consumer<java.lang.Integer>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#pollPendingSatelliteDatagrams(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.pollPendingSatelliteDatagrams(java.util.concurrent.Executor,java.util.function.Consumer<java.lang.Integer>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#provisionSatelliteService(String, byte[], android.os.CancellationSignal, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.provisionSatelliteService(String,byte[],android.os.CancellationSignal,java.util.concurrent.Executor,java.util.function.Consumer<java.lang.Integer>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#registerForSatelliteDatagram(java.util.concurrent.Executor, android.telephony.satellite.SatelliteDatagramCallback): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.registerForSatelliteDatagram(java.util.concurrent.Executor,android.telephony.satellite.SatelliteDatagramCallback) +UnflaggedApi: android.telephony.satellite.SatelliteManager#registerForSatelliteModemStateChanged(java.util.concurrent.Executor, android.telephony.satellite.SatelliteStateCallback): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.registerForSatelliteModemStateChanged(java.util.concurrent.Executor,android.telephony.satellite.SatelliteStateCallback) +UnflaggedApi: android.telephony.satellite.SatelliteManager#registerForSatelliteProvisionStateChanged(java.util.concurrent.Executor, android.telephony.satellite.SatelliteProvisionStateCallback): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.registerForSatelliteProvisionStateChanged(java.util.concurrent.Executor,android.telephony.satellite.SatelliteProvisionStateCallback) +UnflaggedApi: android.telephony.satellite.SatelliteManager#requestIsDemoModeEnabled(java.util.concurrent.Executor, android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.requestIsDemoModeEnabled(java.util.concurrent.Executor,android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#requestIsSatelliteCommunicationAllowedForCurrentLocation(java.util.concurrent.Executor, android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.requestIsSatelliteCommunicationAllowedForCurrentLocation(java.util.concurrent.Executor,android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#requestIsSatelliteEnabled(java.util.concurrent.Executor, android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.requestIsSatelliteEnabled(java.util.concurrent.Executor,android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#requestIsSatelliteProvisioned(java.util.concurrent.Executor, android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.requestIsSatelliteProvisioned(java.util.concurrent.Executor,android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#requestIsSatelliteSupported(java.util.concurrent.Executor, android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.requestIsSatelliteSupported(java.util.concurrent.Executor,android.os.OutcomeReceiver<java.lang.Boolean,android.telephony.satellite.SatelliteManager.SatelliteException>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#requestSatelliteCapabilities(java.util.concurrent.Executor, android.os.OutcomeReceiver<android.telephony.satellite.SatelliteCapabilities,android.telephony.satellite.SatelliteManager.SatelliteException>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.requestSatelliteCapabilities(java.util.concurrent.Executor,android.os.OutcomeReceiver<android.telephony.satellite.SatelliteCapabilities,android.telephony.satellite.SatelliteManager.SatelliteException>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#requestSatelliteEnabled(boolean, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.requestSatelliteEnabled(boolean,boolean,java.util.concurrent.Executor,java.util.function.Consumer<java.lang.Integer>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#requestTimeForNextSatelliteVisibility(java.util.concurrent.Executor, android.os.OutcomeReceiver<java.time.Duration,android.telephony.satellite.SatelliteManager.SatelliteException>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.requestTimeForNextSatelliteVisibility(java.util.concurrent.Executor,android.os.OutcomeReceiver<java.time.Duration,android.telephony.satellite.SatelliteManager.SatelliteException>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#sendSatelliteDatagram(int, android.telephony.satellite.SatelliteDatagram, boolean, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.sendSatelliteDatagram(int,android.telephony.satellite.SatelliteDatagram,boolean,java.util.concurrent.Executor,java.util.function.Consumer<java.lang.Integer>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#setDeviceAlignedWithSatellite(boolean): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.setDeviceAlignedWithSatellite(boolean) +UnflaggedApi: android.telephony.satellite.SatelliteManager#startSatelliteTransmissionUpdates(java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>, android.telephony.satellite.SatelliteTransmissionUpdateCallback): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.startSatelliteTransmissionUpdates(java.util.concurrent.Executor,java.util.function.Consumer<java.lang.Integer>,android.telephony.satellite.SatelliteTransmissionUpdateCallback) +UnflaggedApi: android.telephony.satellite.SatelliteManager#stopSatelliteTransmissionUpdates(android.telephony.satellite.SatelliteTransmissionUpdateCallback, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Integer>): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.stopSatelliteTransmissionUpdates(android.telephony.satellite.SatelliteTransmissionUpdateCallback,java.util.concurrent.Executor,java.util.function.Consumer<java.lang.Integer>) +UnflaggedApi: android.telephony.satellite.SatelliteManager#unregisterForSatelliteDatagram(android.telephony.satellite.SatelliteDatagramCallback): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.unregisterForSatelliteDatagram(android.telephony.satellite.SatelliteDatagramCallback) +UnflaggedApi: android.telephony.satellite.SatelliteManager#unregisterForSatelliteModemStateChanged(android.telephony.satellite.SatelliteStateCallback): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.unregisterForSatelliteModemStateChanged(android.telephony.satellite.SatelliteStateCallback) +UnflaggedApi: android.telephony.satellite.SatelliteManager#unregisterForSatelliteProvisionStateChanged(android.telephony.satellite.SatelliteProvisionStateCallback): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.unregisterForSatelliteProvisionStateChanged(android.telephony.satellite.SatelliteProvisionStateCallback) +UnflaggedApi: android.telephony.satellite.SatelliteManager.SatelliteException: + New API must be flagged with @FlaggedApi: class android.telephony.satellite.SatelliteManager.SatelliteException +UnflaggedApi: android.telephony.satellite.SatelliteManager.SatelliteException#SatelliteException(int): + New API must be flagged with @FlaggedApi: constructor android.telephony.satellite.SatelliteManager.SatelliteException(int) +UnflaggedApi: android.telephony.satellite.SatelliteManager.SatelliteException#getErrorCode(): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteManager.SatelliteException.getErrorCode() +UnflaggedApi: android.telephony.satellite.SatelliteProvisionStateCallback: + New API must be flagged with @FlaggedApi: class android.telephony.satellite.SatelliteProvisionStateCallback +UnflaggedApi: android.telephony.satellite.SatelliteProvisionStateCallback#onSatelliteProvisionStateChanged(boolean): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteProvisionStateCallback.onSatelliteProvisionStateChanged(boolean) +UnflaggedApi: android.telephony.satellite.SatelliteStateCallback: + New API must be flagged with @FlaggedApi: class android.telephony.satellite.SatelliteStateCallback +UnflaggedApi: android.telephony.satellite.SatelliteStateCallback#onSatelliteModemStateChanged(int): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteStateCallback.onSatelliteModemStateChanged(int) +UnflaggedApi: android.telephony.satellite.SatelliteTransmissionUpdateCallback: + New API must be flagged with @FlaggedApi: class android.telephony.satellite.SatelliteTransmissionUpdateCallback +UnflaggedApi: android.telephony.satellite.SatelliteTransmissionUpdateCallback#onReceiveDatagramStateChanged(int, int, int): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteTransmissionUpdateCallback.onReceiveDatagramStateChanged(int,int,int) +UnflaggedApi: android.telephony.satellite.SatelliteTransmissionUpdateCallback#onSatellitePositionChanged(android.telephony.satellite.PointingInfo): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteTransmissionUpdateCallback.onSatellitePositionChanged(android.telephony.satellite.PointingInfo) +UnflaggedApi: android.telephony.satellite.SatelliteTransmissionUpdateCallback#onSendDatagramStateChanged(int, int, int): + New API must be flagged with @FlaggedApi: method android.telephony.satellite.SatelliteTransmissionUpdateCallback.onSendDatagramStateChanged(int,int,int) +UnflaggedApi: android.text.FontConfig#equals(Object): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.equals(Object) +UnflaggedApi: android.text.FontConfig#hashCode(): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.hashCode() +UnflaggedApi: android.text.FontConfig#toString(): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.toString() +UnflaggedApi: android.text.FontConfig.Alias#equals(Object): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.Alias.equals(Object) +UnflaggedApi: android.text.FontConfig.Alias#hashCode(): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.Alias.hashCode() +UnflaggedApi: android.text.FontConfig.Alias#toString(): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.Alias.toString() +UnflaggedApi: android.text.FontConfig.Font#equals(Object): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.Font.equals(Object) +UnflaggedApi: android.text.FontConfig.Font#hashCode(): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.Font.hashCode() +UnflaggedApi: android.text.FontConfig.Font#toString(): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.Font.toString() +UnflaggedApi: android.text.FontConfig.FontFamily#equals(Object): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.FontFamily.equals(Object) +UnflaggedApi: android.text.FontConfig.FontFamily#hashCode(): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.FontFamily.hashCode() +UnflaggedApi: android.text.FontConfig.FontFamily#toString(): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.FontFamily.toString() +UnflaggedApi: android.text.FontConfig.NamedFamilyList#equals(Object): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.NamedFamilyList.equals(Object) +UnflaggedApi: android.text.FontConfig.NamedFamilyList#hashCode(): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.NamedFamilyList.hashCode() +UnflaggedApi: android.text.FontConfig.NamedFamilyList#toString(): + New API must be flagged with @FlaggedApi: method android.text.FontConfig.NamedFamilyList.toString() +UnflaggedApi: android.view.contentcapture.ContentCaptureEvent#toString(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ContentCaptureEvent.toString() +UnflaggedApi: android.view.contentcapture.ViewNode#getAutofillHints(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getAutofillHints() +UnflaggedApi: android.view.contentcapture.ViewNode#getAutofillId(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getAutofillId() +UnflaggedApi: android.view.contentcapture.ViewNode#getAutofillOptions(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getAutofillOptions() +UnflaggedApi: android.view.contentcapture.ViewNode#getAutofillType(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getAutofillType() +UnflaggedApi: android.view.contentcapture.ViewNode#getAutofillValue(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getAutofillValue() +UnflaggedApi: android.view.contentcapture.ViewNode#getClassName(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getClassName() +UnflaggedApi: android.view.contentcapture.ViewNode#getContentDescription(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getContentDescription() +UnflaggedApi: android.view.contentcapture.ViewNode#getExtras(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getExtras() +UnflaggedApi: android.view.contentcapture.ViewNode#getHeight(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getHeight() +UnflaggedApi: android.view.contentcapture.ViewNode#getHint(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getHint() +UnflaggedApi: android.view.contentcapture.ViewNode#getHintIdEntry(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getHintIdEntry() +UnflaggedApi: android.view.contentcapture.ViewNode#getId(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getId() +UnflaggedApi: android.view.contentcapture.ViewNode#getIdEntry(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getIdEntry() +UnflaggedApi: android.view.contentcapture.ViewNode#getIdPackage(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getIdPackage() +UnflaggedApi: android.view.contentcapture.ViewNode#getIdType(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getIdType() +UnflaggedApi: android.view.contentcapture.ViewNode#getInputType(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getInputType() +UnflaggedApi: android.view.contentcapture.ViewNode#getLeft(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getLeft() +UnflaggedApi: android.view.contentcapture.ViewNode#getLocaleList(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getLocaleList() +UnflaggedApi: android.view.contentcapture.ViewNode#getMaxTextEms(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getMaxTextEms() +UnflaggedApi: android.view.contentcapture.ViewNode#getMaxTextLength(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getMaxTextLength() +UnflaggedApi: android.view.contentcapture.ViewNode#getMinTextEms(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getMinTextEms() +UnflaggedApi: android.view.contentcapture.ViewNode#getReceiveContentMimeTypes(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getReceiveContentMimeTypes() +UnflaggedApi: android.view.contentcapture.ViewNode#getScrollX(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getScrollX() +UnflaggedApi: android.view.contentcapture.ViewNode#getScrollY(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getScrollY() +UnflaggedApi: android.view.contentcapture.ViewNode#getText(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getText() +UnflaggedApi: android.view.contentcapture.ViewNode#getTextBackgroundColor(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getTextBackgroundColor() +UnflaggedApi: android.view.contentcapture.ViewNode#getTextColor(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getTextColor() +UnflaggedApi: android.view.contentcapture.ViewNode#getTextIdEntry(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getTextIdEntry() +UnflaggedApi: android.view.contentcapture.ViewNode#getTextLineBaselines(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getTextLineBaselines() +UnflaggedApi: android.view.contentcapture.ViewNode#getTextLineCharOffsets(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getTextLineCharOffsets() +UnflaggedApi: android.view.contentcapture.ViewNode#getTextSelectionEnd(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getTextSelectionEnd() +UnflaggedApi: android.view.contentcapture.ViewNode#getTextSelectionStart(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getTextSelectionStart() +UnflaggedApi: android.view.contentcapture.ViewNode#getTextSize(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getTextSize() +UnflaggedApi: android.view.contentcapture.ViewNode#getTextStyle(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getTextStyle() +UnflaggedApi: android.view.contentcapture.ViewNode#getTop(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getTop() +UnflaggedApi: android.view.contentcapture.ViewNode#getVisibility(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getVisibility() +UnflaggedApi: android.view.contentcapture.ViewNode#getWidth(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.getWidth() +UnflaggedApi: android.view.contentcapture.ViewNode#isAccessibilityFocused(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isAccessibilityFocused() +UnflaggedApi: android.view.contentcapture.ViewNode#isActivated(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isActivated() +UnflaggedApi: android.view.contentcapture.ViewNode#isAssistBlocked(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isAssistBlocked() +UnflaggedApi: android.view.contentcapture.ViewNode#isCheckable(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isCheckable() +UnflaggedApi: android.view.contentcapture.ViewNode#isChecked(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isChecked() +UnflaggedApi: android.view.contentcapture.ViewNode#isClickable(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isClickable() +UnflaggedApi: android.view.contentcapture.ViewNode#isContextClickable(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isContextClickable() +UnflaggedApi: android.view.contentcapture.ViewNode#isEnabled(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isEnabled() +UnflaggedApi: android.view.contentcapture.ViewNode#isFocusable(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isFocusable() +UnflaggedApi: android.view.contentcapture.ViewNode#isFocused(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isFocused() +UnflaggedApi: android.view.contentcapture.ViewNode#isLongClickable(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isLongClickable() +UnflaggedApi: android.view.contentcapture.ViewNode#isOpaque(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isOpaque() +UnflaggedApi: android.view.contentcapture.ViewNode#isSelected(): + New API must be flagged with @FlaggedApi: method android.view.contentcapture.ViewNode.isSelected() +UnflaggedApi: android.view.translation.UiTranslationSpec#equals(Object): + New API must be flagged with @FlaggedApi: method android.view.translation.UiTranslationSpec.equals(Object) +UnflaggedApi: android.view.translation.UiTranslationSpec#hashCode(): + New API must be flagged with @FlaggedApi: method android.view.translation.UiTranslationSpec.hashCode() +UnflaggedApi: android.view.translation.UiTranslationSpec#toString(): + New API must be flagged with @FlaggedApi: method android.view.translation.UiTranslationSpec.toString() diff --git a/core/java/android/hardware/radio/ProgramList.java b/core/java/android/hardware/radio/ProgramList.java index b2dfd8501772..4f07acf6961a 100644 --- a/core/java/android/hardware/radio/ProgramList.java +++ b/core/java/android/hardware/radio/ProgramList.java @@ -23,6 +23,7 @@ import android.annotation.SystemApi; import android.os.Parcel; import android.os.Parcelable; import android.util.ArrayMap; +import android.util.ArraySet; import com.android.internal.annotations.GuardedBy; @@ -34,7 +35,6 @@ import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.concurrent.Executor; -import java.util.stream.Collectors; /** * @hide @@ -45,8 +45,8 @@ public final class ProgramList implements AutoCloseable { private final Object mLock = new Object(); @GuardedBy("mLock") - private final Map<ProgramSelector.Identifier, RadioManager.ProgramInfo> mPrograms = - new ArrayMap<>(); + private final Map<ProgramSelector.Identifier, Map<UniqueProgramIdentifier, + RadioManager.ProgramInfo>> mPrograms = new ArrayMap<>(); @GuardedBy("mLock") private final List<ListCallback> mListCallbacks = new ArrayList<>(); @@ -193,7 +193,7 @@ public final class ProgramList implements AutoCloseable { void apply(Chunk chunk) { List<ProgramSelector.Identifier> removedList = new ArrayList<>(); - List<ProgramSelector.Identifier> changedList = new ArrayList<>(); + Set<ProgramSelector.Identifier> changedSet = new ArraySet<>(); List<ProgramList.ListCallback> listCallbacksCopied; List<OnCompleteListener> onCompleteListenersCopied = new ArrayList<>(); synchronized (mLock) { @@ -203,19 +203,27 @@ public final class ProgramList implements AutoCloseable { listCallbacksCopied = new ArrayList<>(mListCallbacks); if (chunk.isPurge()) { - Iterator<Map.Entry<ProgramSelector.Identifier, RadioManager.ProgramInfo>> - programsIterator = mPrograms.entrySet().iterator(); + Iterator<Map.Entry<ProgramSelector.Identifier, Map<UniqueProgramIdentifier, + RadioManager.ProgramInfo>>> programsIterator = + mPrograms.entrySet().iterator(); while (programsIterator.hasNext()) { - RadioManager.ProgramInfo removed = programsIterator.next().getValue(); - if (removed != null) { - removedList.add(removed.getSelector().getPrimaryId()); + Map.Entry<ProgramSelector.Identifier, Map<UniqueProgramIdentifier, + RadioManager.ProgramInfo>> removed = programsIterator.next(); + if (removed.getValue() != null) { + removedList.add(removed.getKey()); } programsIterator.remove(); } } - chunk.getRemoved().stream().forEach(id -> removeLocked(id, removedList)); - chunk.getModified().stream().forEach(info -> putLocked(info, changedList)); + Iterator<UniqueProgramIdentifier> removedIterator = chunk.getRemoved().iterator(); + while (removedIterator.hasNext()) { + removeLocked(removedIterator.next(), removedList); + } + Iterator<RadioManager.ProgramInfo> modifiedIterator = chunk.getModified().iterator(); + while (modifiedIterator.hasNext()) { + putLocked(modifiedIterator.next(), changedSet); + } if (chunk.isComplete()) { mIsComplete = true; @@ -228,9 +236,11 @@ public final class ProgramList implements AutoCloseable { listCallbacksCopied.get(cbIndex).onItemRemoved(removedList.get(i)); } } - for (int i = 0; i < changedList.size(); i++) { + Iterator<ProgramSelector.Identifier> changedIterator = changedSet.iterator(); + while (changedIterator.hasNext()) { + ProgramSelector.Identifier changedId = changedIterator.next(); for (int cbIndex = 0; cbIndex < listCallbacksCopied.size(); cbIndex++) { - listCallbacksCopied.get(cbIndex).onItemChanged(changedList.get(i)); + listCallbacksCopied.get(cbIndex).onItemChanged(changedId); } } if (chunk.isComplete()) { @@ -242,20 +252,31 @@ public final class ProgramList implements AutoCloseable { @GuardedBy("mLock") private void putLocked(RadioManager.ProgramInfo value, - List<ProgramSelector.Identifier> changedIdentifierList) { - ProgramSelector.Identifier key = value.getSelector().getPrimaryId(); - mPrograms.put(Objects.requireNonNull(key), value); - ProgramSelector.Identifier sel = value.getSelector().getPrimaryId(); - changedIdentifierList.add(sel); + Set<ProgramSelector.Identifier> changedIdentifierSet) { + UniqueProgramIdentifier key = new UniqueProgramIdentifier( + value.getSelector()); + ProgramSelector.Identifier primaryKey = Objects.requireNonNull(key.getPrimaryId()); + if (!mPrograms.containsKey(primaryKey)) { + mPrograms.put(primaryKey, new ArrayMap<>()); + } + mPrograms.get(primaryKey).put(key, value); + changedIdentifierSet.add(primaryKey); } @GuardedBy("mLock") - private void removeLocked(ProgramSelector.Identifier key, + private void removeLocked(UniqueProgramIdentifier key, List<ProgramSelector.Identifier> removedIdentifierList) { - RadioManager.ProgramInfo removed = mPrograms.remove(Objects.requireNonNull(key)); + ProgramSelector.Identifier primaryKey = Objects.requireNonNull(key.getPrimaryId()); + if (!mPrograms.containsKey(primaryKey)) { + return; + } + Map<UniqueProgramIdentifier, RadioManager.ProgramInfo> entries = mPrograms + .get(primaryKey); + RadioManager.ProgramInfo removed = entries.remove(Objects.requireNonNull(key)); if (removed == null) return; - ProgramSelector.Identifier sel = removed.getSelector().getPrimaryId(); - removedIdentifierList.add(sel); + if (entries.size() == 0) { + removedIdentifierList.add(primaryKey); + } } /** @@ -264,9 +285,20 @@ public final class ProgramList implements AutoCloseable { * @return the new List<> object; it won't receive any further updates */ public @NonNull List<RadioManager.ProgramInfo> toList() { + List<RadioManager.ProgramInfo> list = new ArrayList<>(); synchronized (mLock) { - return mPrograms.values().stream().collect(Collectors.toList()); + Iterator<Map.Entry<ProgramSelector.Identifier, Map<UniqueProgramIdentifier, + RadioManager.ProgramInfo>>> listIterator = mPrograms.entrySet().iterator(); + while (listIterator.hasNext()) { + Iterator<Map.Entry<UniqueProgramIdentifier, + RadioManager.ProgramInfo>> prorgramsIterator = listIterator.next() + .getValue().entrySet().iterator(); + while (prorgramsIterator.hasNext()) { + list.add(prorgramsIterator.next().getValue()); + } + } } + return list; } /** @@ -276,9 +308,15 @@ public final class ProgramList implements AutoCloseable { * @return the program info, or null if there is no such program on the list */ public @Nullable RadioManager.ProgramInfo get(@NonNull ProgramSelector.Identifier id) { + Map<UniqueProgramIdentifier, RadioManager.ProgramInfo> entries; synchronized (mLock) { - return mPrograms.get(Objects.requireNonNull(id)); + entries = mPrograms.get(Objects.requireNonNull(id, + "Primary identifier can not be null")); + } + if (entries == null) { + return null; } + return entries.entrySet().iterator().next().getValue(); } /** @@ -404,7 +442,7 @@ public final class ProgramList implements AutoCloseable { * Checks, if non-tunable entries that define tree structure on the * program list (i.e. DAB ensembles) should be included. * - * @see {@link ProgramSelector.Identifier#isCategory()} + * @see ProgramSelector.Identifier#isCategoryType() */ public boolean areCategoriesIncluded() { return mIncludeCategories; @@ -459,11 +497,11 @@ public final class ProgramList implements AutoCloseable { private final boolean mPurge; private final boolean mComplete; private final @NonNull Set<RadioManager.ProgramInfo> mModified; - private final @NonNull Set<ProgramSelector.Identifier> mRemoved; + private final @NonNull Set<UniqueProgramIdentifier> mRemoved; public Chunk(boolean purge, boolean complete, @Nullable Set<RadioManager.ProgramInfo> modified, - @Nullable Set<ProgramSelector.Identifier> removed) { + @Nullable Set<UniqueProgramIdentifier> removed) { mPurge = purge; mComplete = complete; mModified = (modified != null) ? modified : Collections.emptySet(); @@ -474,7 +512,7 @@ public final class ProgramList implements AutoCloseable { mPurge = in.readByte() != 0; mComplete = in.readByte() != 0; mModified = Utils.createSet(in, RadioManager.ProgramInfo.CREATOR); - mRemoved = Utils.createSet(in, ProgramSelector.Identifier.CREATOR); + mRemoved = Utils.createSet(in, UniqueProgramIdentifier.CREATOR); } @Override @@ -512,7 +550,7 @@ public final class ProgramList implements AutoCloseable { return mModified; } - public @NonNull Set<ProgramSelector.Identifier> getRemoved() { + public @NonNull Set<UniqueProgramIdentifier> getRemoved() { return mRemoved; } diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java index c6cb604d4039..80b7d40c14c5 100644 --- a/core/java/android/os/UserManager.java +++ b/core/java/android/os/UserManager.java @@ -4663,26 +4663,6 @@ public class UserManager { } /** - * Returns number of full users on the device. - * @hide - */ - @RequiresPermission(anyOf = { - android.Manifest.permission.MANAGE_USERS, - android.Manifest.permission.CREATE_USERS - }) - public int getFullUserCount() { - List<UserInfo> users = getUsers(/* excludePartial= */ true, /* excludeDying= */ true, - /* excludePreCreated= */ true); - int count = 0; - for (UserInfo user : users) { - if (user.isFull()) { - count++; - } - } - return count; - } - - /** * @deprecated use {@link #getAliveUsers()} for {@code getUsers(true)}, or * {@link #getUsers()} for @code getUsers(false)}. * diff --git a/core/java/android/security/FileIntegrityManager.java b/core/java/android/security/FileIntegrityManager.java index d6f3bf334456..132700d289b8 100644 --- a/core/java/android/security/FileIntegrityManager.java +++ b/core/java/android/security/FileIntegrityManager.java @@ -133,13 +133,11 @@ public final class FileIntegrityManager { * also use this API to download the best signature on the running device. * * @return whether the certificate is trusted in the system - * @deprecated The feature is no longer supported, and this API now always returns false. */ @RequiresPermission(anyOf = { android.Manifest.permission.INSTALL_PACKAGES, android.Manifest.permission.REQUEST_INSTALL_PACKAGES }) - @Deprecated public boolean isAppSourceCertificateTrusted(@NonNull X509Certificate certificate) throws CertificateEncodingException { try { diff --git a/core/java/android/service/voice/HotwordTrainingAudio.java b/core/java/android/service/voice/HotwordTrainingAudio.java index 895b0c0e2d55..91e34dcc4a64 100644 --- a/core/java/android/service/voice/HotwordTrainingAudio.java +++ b/core/java/android/service/voice/HotwordTrainingAudio.java @@ -18,6 +18,7 @@ package android.service.voice; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.annotation.SystemApi; import android.media.AudioFormat; import android.os.Parcel; @@ -25,6 +26,8 @@ import android.os.Parcelable; import com.android.internal.util.DataClass; +import java.util.Objects; + /** * Represents audio supporting hotword model training. * @@ -43,7 +46,10 @@ public final class HotwordTrainingAudio implements Parcelable { /** Represents unset value for the hotword offset. */ public static final int HOTWORD_OFFSET_UNSET = -1; - /** Buffer of hotword audio data for training models. */ + /** + * Buffer of hotword audio data for training models. The data format is expected to match + * {@link #getAudioFormat()}. + */ @NonNull private final byte[] mHotwordAudio; @@ -74,6 +80,24 @@ public final class HotwordTrainingAudio implements Parcelable { */ private int mHotwordOffsetMillis = HOTWORD_OFFSET_UNSET; + @DataClass.Suppress("setHotwordAudio") + abstract static class BaseBuilder { + + /** + * Buffer of hotword audio data for training models. The data format is expected to match + * {@link #getAudioFormat()}. + */ + @SuppressLint("UnflaggedApi") + public @NonNull HotwordTrainingAudio.Builder setHotwordAudio(@NonNull byte[] value) { + Objects.requireNonNull(value, "value should not be null"); + final HotwordTrainingAudio.Builder builder = (HotwordTrainingAudio.Builder) this; + // If the code gen flag in build() is changed, we must update the flag e.g. 0x1 here. + builder.mBuilderFieldsSet |= 0x1; + builder.mHotwordAudio = value; + return builder; + } + } + // Code below generated by codegen v1.0.23. @@ -110,7 +134,8 @@ public final class HotwordTrainingAudio implements Parcelable { } /** - * Buffer of hotword audio data for training models. + * Buffer of hotword audio data for training models. The data format is expected to match + * {@link #getAudioFormat()}. */ @DataClass.Generated.Member public @NonNull byte[] getHotwordAudio() { @@ -171,7 +196,7 @@ public final class HotwordTrainingAudio implements Parcelable { //noinspection PointlessBooleanExpression return true && java.util.Arrays.equals(mHotwordAudio, that.mHotwordAudio) - && java.util.Objects.equals(mAudioFormat, that.mAudioFormat) + && Objects.equals(mAudioFormat, that.mAudioFormat) && mAudioType == that.mAudioType && mHotwordOffsetMillis == that.mHotwordOffsetMillis; } @@ -184,7 +209,7 @@ public final class HotwordTrainingAudio implements Parcelable { int _hash = 1; _hash = 31 * _hash + java.util.Arrays.hashCode(mHotwordAudio); - _hash = 31 * _hash + java.util.Objects.hashCode(mAudioFormat); + _hash = 31 * _hash + Objects.hashCode(mAudioFormat); _hash = 31 * _hash + mAudioType; _hash = 31 * _hash + mHotwordOffsetMillis; return _hash; @@ -251,7 +276,7 @@ public final class HotwordTrainingAudio implements Parcelable { */ @SuppressWarnings("WeakerAccess") @DataClass.Generated.Member - public static final class Builder { + public static final class Builder extends BaseBuilder { private @NonNull byte[] mHotwordAudio; private @NonNull AudioFormat mAudioFormat; @@ -264,7 +289,8 @@ public final class HotwordTrainingAudio implements Parcelable { * Creates a new Builder. * * @param hotwordAudio - * Buffer of hotword audio data for training models. + * Buffer of hotword audio data for training models. The data format is expected to match + * {@link #getAudioFormat()}. * @param audioFormat * The {@link AudioFormat} of the {@link HotwordTrainingAudio#mHotwordAudio}. */ @@ -280,17 +306,6 @@ public final class HotwordTrainingAudio implements Parcelable { } /** - * Buffer of hotword audio data for training models. - */ - @DataClass.Generated.Member - public @NonNull Builder setHotwordAudio(@NonNull byte... value) { - checkNotUsed(); - mBuilderFieldsSet |= 0x1; - mHotwordAudio = value; - return this; - } - - /** * The {@link AudioFormat} of the {@link HotwordTrainingAudio#mHotwordAudio}. */ @DataClass.Generated.Member @@ -353,10 +368,10 @@ public final class HotwordTrainingAudio implements Parcelable { } @DataClass.Generated( - time = 1692837160437L, + time = 1694193905346L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/core/java/android/service/voice/HotwordTrainingAudio.java", - inputSignatures = "public static final int HOTWORD_OFFSET_UNSET\nprivate final @android.annotation.NonNull byte[] mHotwordAudio\nprivate final @android.annotation.NonNull android.media.AudioFormat mAudioFormat\nprivate final @android.annotation.NonNull int mAudioType\nprivate int mHotwordOffsetMillis\nprivate java.lang.String hotwordAudioToString()\nprivate static int defaultAudioType()\nclass HotwordTrainingAudio extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)") + inputSignatures = "public static final int HOTWORD_OFFSET_UNSET\nprivate final @android.annotation.NonNull byte[] mHotwordAudio\nprivate final @android.annotation.NonNull android.media.AudioFormat mAudioFormat\nprivate final @android.annotation.NonNull int mAudioType\nprivate int mHotwordOffsetMillis\nprivate java.lang.String hotwordAudioToString()\nprivate static int defaultAudioType()\nclass HotwordTrainingAudio extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.service.voice.HotwordTrainingAudio.Builder setHotwordAudio(byte[])\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.service.voice.HotwordTrainingAudio.Builder setHotwordAudio(byte[])\nclass BaseBuilder extends java.lang.Object implements []") @Deprecated private void __metadata() {} diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index b8385c6ecba9..e64274ec3892 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -3139,15 +3139,6 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS = 1 << 10; /** - * Flag to force the status bar window to be visible all the time. If the bar is hidden when - * this flag is set it will be shown again. - * This can only be set by {@link LayoutParams#TYPE_STATUS_BAR}. - * - * {@hide} - */ - public static final int PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR = 1 << 11; - - /** * Flag to indicate that the window frame should be the requested frame adding the display * cutout frame. This will only be applied if a specific size smaller than the parent frame * is given, and the window is covering the display cutout. The extended frame will not be @@ -3238,15 +3229,6 @@ public interface WindowManager extends ViewManager { public static final int PRIVATE_FLAG_NOT_MAGNIFIABLE = 1 << 22; /** - * Flag to indicate that the status bar window is in a state such that it forces showing - * the navigation bar unless the navigation bar window is explicitly set to - * {@link View#GONE}. - * It only takes effects if this is set by {@link LayoutParams#TYPE_STATUS_BAR}. - * @hide - */ - public static final int PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION = 1 << 23; - - /** * Flag to indicate that the window is color space agnostic, and the color can be * interpreted to any color space. * @hide @@ -3334,7 +3316,6 @@ public interface WindowManager extends ViewManager { PRIVATE_FLAG_SYSTEM_ERROR, PRIVATE_FLAG_OPTIMIZE_MEASURE, PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS, - PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR, PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT, PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY, PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME, @@ -3345,7 +3326,6 @@ public interface WindowManager extends ViewManager { PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION, PRIVATE_FLAG_NOT_MAGNIFIABLE, - PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC, PRIVATE_FLAG_USE_BLAST, PRIVATE_FLAG_APPEARANCE_CONTROLLED, @@ -3401,10 +3381,6 @@ public interface WindowManager extends ViewManager { equals = PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS, name = "DISABLE_WALLPAPER_TOUCH_EVENTS"), @ViewDebug.FlagToString( - mask = PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR, - equals = PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR, - name = "FORCE_STATUS_BAR_VISIBLE"), - @ViewDebug.FlagToString( mask = PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT, equals = PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT, name = "LAYOUT_SIZE_EXTENDED_BY_CUTOUT"), @@ -3445,10 +3421,6 @@ public interface WindowManager extends ViewManager { equals = PRIVATE_FLAG_NOT_MAGNIFIABLE, name = "NOT_MAGNIFIABLE"), @ViewDebug.FlagToString( - mask = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, - equals = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, - name = "STATUS_FORCE_SHOW_NAVIGATION"), - @ViewDebug.FlagToString( mask = PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC, equals = PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC, name = "COLOR_SPACE_AGNOSTIC"), @@ -4412,6 +4384,16 @@ public interface WindowManager extends ViewManager { public InsetsFrameProvider[] providedInsets; /** + * Specifies which {@link InsetsType}s should be forcibly shown. The types shown by this + * method won't affect the app's layout. This field only takes effects if the caller has + * {@link android.Manifest.permission#STATUS_BAR_SERVICE} or the caller has the same uid as + * the recents component. + * + * @hide + */ + public @InsetsType int forciblyShownTypes; + + /** * {@link LayoutParams} to be applied to the window when layout with a assigned rotation. * This will make layout during rotation change smoothly. * @@ -4869,6 +4851,7 @@ public interface WindowManager extends ViewManager { out.writeInt(mBlurBehindRadius); out.writeBoolean(mWallpaperTouchEventsEnabled); out.writeTypedArray(providedInsets, 0 /* parcelableFlags */); + out.writeInt(forciblyShownTypes); checkNonRecursiveParams(); out.writeTypedArray(paramsForRotation, 0 /* parcelableFlags */); out.writeInt(mDisplayFlags); @@ -4940,6 +4923,7 @@ public interface WindowManager extends ViewManager { mBlurBehindRadius = in.readInt(); mWallpaperTouchEventsEnabled = in.readBoolean(); providedInsets = in.createTypedArray(InsetsFrameProvider.CREATOR); + forciblyShownTypes = in.readInt(); paramsForRotation = in.createTypedArray(LayoutParams.CREATOR); mDisplayFlags = in.readInt(); } @@ -5245,6 +5229,11 @@ public interface WindowManager extends ViewManager { changes |= LAYOUT_CHANGED; } + if (forciblyShownTypes != o.forciblyShownTypes) { + forciblyShownTypes = o.forciblyShownTypes; + changes |= PRIVATE_FLAGS_CHANGED; + } + if (paramsForRotation != o.paramsForRotation) { if ((changes & LAYOUT_CHANGED) == 0) { if (paramsForRotation != null && o.paramsForRotation != null @@ -5482,6 +5471,11 @@ public interface WindowManager extends ViewManager { sb.append(prefix).append(" ").append(providedInsets[i]); } } + if (forciblyShownTypes != 0) { + sb.append(System.lineSeparator()); + sb.append(prefix).append(" forciblyShownTypes=").append( + WindowInsets.Type.toString(forciblyShownTypes)); + } if (paramsForRotation != null && paramsForRotation.length != 0) { sb.append(System.lineSeparator()); sb.append(prefix).append(" paramsForRotation:"); diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index 32fe4e3e4104..3180ffbef79d 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -1466,10 +1466,9 @@ <!-- Allows an application to initiate a phone call without going through the Dialer user interface for the user to confirm the call. - <p> - <em>Note: An app holding this permission can also call carrier MMI codes to change settings - such as call forwarding or call waiting preferences. - <p>Protection level: dangerous + <p class="note"><b>Note:</b> An app holding this permission can also call carrier MMI + codes to change settings such as call forwarding or call waiting preferences.</p> + <p>Protection level: dangerous</p> --> <permission android:name="android.permission.CALL_PHONE" android:permissionGroup="android.permission-group.UNDEFINED" diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 7d2690eabc96..e7764d8b1fde 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -5717,13 +5717,13 @@ <!-- Blur radius for the Option 3 in R.integer.config_letterboxBackgroundType. Values < 0 are ignored and 0 is used. --> - <dimen name="config_letterboxBackgroundWallpaperBlurRadius">24dp</dimen> + <dimen name="config_letterboxBackgroundWallpaperBlurRadius">38dp</dimen> <!-- Alpha of a black translucent scrim showed over wallpaper letterbox background when the Option 3 is selected for R.integer.config_letterboxBackgroundType. Values < 0 or >= 1 are ignored and 0.0 (transparent) is used instead. --> <item name="config_letterboxBackgroundWallaperDarkScrimAlpha" format="float" type="dimen"> - 0.75 + 0.54 </item> <!-- Corners appearance of the letterbox background. diff --git a/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramListTest.java b/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramListTest.java index 7c3d2f2138a4..d638fedc5358 100644 --- a/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramListTest.java +++ b/core/tests/BroadcastRadioTests/src/android/hardware/radio/ProgramListTest.java @@ -74,18 +74,45 @@ public final class ProgramListTest { private static final ProgramSelector.Identifier DAB_ENSEMBLE_IDENTIFIER = new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE, /* value= */ 0x1013); + private static final ProgramSelector.Identifier DAB_FREQUENCY_IDENTIFIER_1 = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, + /* value= */ 222_064); + private static final ProgramSelector.Identifier DAB_FREQUENCY_IDENTIFIER_2 = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, + /* value= */ 220_352); + + private static final ProgramSelector DAB_SELECTOR_1 = new ProgramSelector( + ProgramSelector.PROGRAM_TYPE_DAB, DAB_DMB_SID_EXT_IDENTIFIER, + new ProgramSelector.Identifier[]{DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER_1}, + /* vendorIds= */ null); + private static final ProgramSelector DAB_SELECTOR_2 = new ProgramSelector( + ProgramSelector.PROGRAM_TYPE_DAB, DAB_DMB_SID_EXT_IDENTIFIER, + new ProgramSelector.Identifier[]{DAB_ENSEMBLE_IDENTIFIER, DAB_FREQUENCY_IDENTIFIER_2}, + /* vendorIds= */ null); + + private static final UniqueProgramIdentifier RDS_UNIQUE_IDENTIFIER = + new UniqueProgramIdentifier(RDS_IDENTIFIER); + private static final UniqueProgramIdentifier DAB_UNIQUE_IDENTIFIER_1 = + new UniqueProgramIdentifier(DAB_SELECTOR_1); + private static final UniqueProgramIdentifier DAB_UNIQUE_IDENTIFIER_2 = + new UniqueProgramIdentifier(DAB_SELECTOR_2); + private static final RadioManager.ProgramInfo FM_PROGRAM_INFO = createFmProgramInfo( createProgramSelector(ProgramSelector.PROGRAM_TYPE_FM, FM_IDENTIFIER)); - private static final RadioManager.ProgramInfo RDS_PROGRAM_INFO = createFmProgramInfo( - createProgramSelector(ProgramSelector.PROGRAM_TYPE_FM, RDS_IDENTIFIER)); + private static final RadioManager.ProgramInfo DAB_PROGRAM_INFO_1 = createDabProgramInfo( + DAB_SELECTOR_1); + private static final RadioManager.ProgramInfo DAB_PROGRAM_INFO_2 = createDabProgramInfo( + DAB_SELECTOR_2); private static final Set<Integer> FILTER_IDENTIFIER_TYPES = Set.of( - ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, ProgramSelector.IDENTIFIER_TYPE_RDS_PI); - private static final Set<ProgramSelector.Identifier> FILTER_IDENTIFIERS = Set.of(FM_IDENTIFIER); - - private static final ProgramList.Chunk FM_RDS_ADD_CHUNK = new ProgramList.Chunk(IS_PURGE, - IS_COMPLETE, Set.of(FM_PROGRAM_INFO, RDS_PROGRAM_INFO), - Set.of(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER)); + ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, + ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT); + private static final Set<ProgramSelector.Identifier> FILTER_IDENTIFIERS = Set.of( + FM_IDENTIFIER, DAB_DMB_SID_EXT_IDENTIFIER); + + private static final ProgramList.Chunk FM_DAB_ADD_CHUNK = new ProgramList.Chunk(IS_PURGE, + IS_COMPLETE, Set.of(FM_PROGRAM_INFO, DAB_PROGRAM_INFO_1, DAB_PROGRAM_INFO_2), + Set.of(RDS_UNIQUE_IDENTIFIER)); private static final ProgramList.Chunk FM_ADD_INCOMPLETE_CHUNK = new ProgramList.Chunk(IS_PURGE, /* complete= */ false, Set.of(FM_PROGRAM_INFO), new ArraySet<>()); private static final ProgramList.Filter TEST_FILTER = new ProgramList.Filter( @@ -213,58 +240,44 @@ public final class ProgramListTest { @Test public void isPurge_forChunk() { - ProgramList.Chunk chunk = new ProgramList.Chunk(IS_PURGE, IS_COMPLETE, - Set.of(FM_PROGRAM_INFO, RDS_PROGRAM_INFO), - Set.of(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER)); - - assertWithMessage("Puring chunk").that(chunk.isPurge()).isEqualTo(IS_PURGE); + assertWithMessage("Puring chunk").that(FM_DAB_ADD_CHUNK.isPurge()).isEqualTo(IS_PURGE); } @Test public void isComplete_forChunk() { - ProgramList.Chunk chunk = new ProgramList.Chunk(IS_PURGE, IS_COMPLETE, - Set.of(FM_PROGRAM_INFO, RDS_PROGRAM_INFO), - Set.of(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER)); - - assertWithMessage("Complete chunk").that(chunk.isComplete()).isEqualTo(IS_COMPLETE); + assertWithMessage("Complete chunk").that(FM_DAB_ADD_CHUNK.isComplete()) + .isEqualTo(IS_COMPLETE); } @Test public void getModified_forChunk() { - ProgramList.Chunk chunk = new ProgramList.Chunk(IS_PURGE, IS_COMPLETE, - Set.of(FM_PROGRAM_INFO, RDS_PROGRAM_INFO), - Set.of(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER)); - assertWithMessage("Modified program info in chunk") - .that(chunk.getModified()).containsExactly(FM_PROGRAM_INFO, RDS_PROGRAM_INFO); + .that(FM_DAB_ADD_CHUNK.getModified()) + .containsExactly(FM_PROGRAM_INFO, DAB_PROGRAM_INFO_1, DAB_PROGRAM_INFO_2); } @Test public void getRemoved_forChunk() { - ProgramList.Chunk chunk = new ProgramList.Chunk(IS_PURGE, IS_COMPLETE, - Set.of(FM_PROGRAM_INFO, RDS_PROGRAM_INFO), - Set.of(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER)); - - assertWithMessage("Removed program identifiers in chunk").that(chunk.getRemoved()) - .containsExactly(DAB_DMB_SID_EXT_IDENTIFIER, DAB_ENSEMBLE_IDENTIFIER); + assertWithMessage("Removed program identifiers in chunk") + .that(FM_DAB_ADD_CHUNK.getRemoved()).containsExactly(RDS_UNIQUE_IDENTIFIER); } @Test public void describeContents_forChunk() { - assertWithMessage("Chunk contents").that(FM_RDS_ADD_CHUNK.describeContents()).isEqualTo(0); + assertWithMessage("Chunk contents").that(FM_DAB_ADD_CHUNK.describeContents()).isEqualTo(0); } @Test public void writeToParcel_forChunk() { Parcel parcel = Parcel.obtain(); - FM_RDS_ADD_CHUNK.writeToParcel(parcel, /* flags= */ 0); + FM_DAB_ADD_CHUNK.writeToParcel(parcel, /* flags= */ 0); parcel.setDataPosition(0); ProgramList.Chunk chunkFromParcel = ProgramList.Chunk.CREATOR.createFromParcel(parcel); assertWithMessage("Chunk created from parcel") - .that(chunkFromParcel).isEqualTo(FM_RDS_ADD_CHUNK); + .that(chunkFromParcel).isEqualTo(FM_DAB_ADD_CHUNK); } @Test @@ -336,37 +349,78 @@ public final class ProgramListTest { } @Test - public void onProgramListUpdated_withNewIdsAdded_invokesMockedCallbacks() throws Exception { + public void onProgramListUpdated_withNewIdsAdded_invokesCallbacks() throws Exception { createRadioTuner(); mProgramList = mRadioTuner.getDynamicProgramList(TEST_FILTER); registerListCallbacks(/* numCallbacks= */ 1); addOnCompleteListeners(/* numListeners= */ 1); - mTunerCallback.onProgramListUpdated(FM_RDS_ADD_CHUNK); + mTunerCallback.onProgramListUpdated(FM_DAB_ADD_CHUNK); verify(mListCallbackMocks[0], CALLBACK_TIMEOUT).onItemChanged(FM_IDENTIFIER); - verify(mListCallbackMocks[0], CALLBACK_TIMEOUT).onItemChanged(RDS_IDENTIFIER); + verify(mListCallbackMocks[0], CALLBACK_TIMEOUT).onItemChanged(DAB_DMB_SID_EXT_IDENTIFIER); verify(mOnCompleteListenerMocks[0], CALLBACK_TIMEOUT).onComplete(); - assertWithMessage("Program info in program list after adding FM and RDS info") - .that(mProgramList.toList()).containsExactly(FM_PROGRAM_INFO, RDS_PROGRAM_INFO); + assertWithMessage("Program info in program list after adding FM and DAB info") + .that(mProgramList.toList()).containsExactly(FM_PROGRAM_INFO, DAB_PROGRAM_INFO_1, + DAB_PROGRAM_INFO_2); } @Test - public void onProgramListUpdated_withIdsRemoved_invokesMockedCallbacks() throws Exception { + public void onProgramListUpdated_withFmIdsRemoved_invokesCallbacks() throws Exception { + UniqueProgramIdentifier fmUniqueId = new UniqueProgramIdentifier(FM_IDENTIFIER); ProgramList.Chunk fmRemovedChunk = new ProgramList.Chunk(/* purge= */ false, - /* complete= */ false, new ArraySet<>(), Set.of(FM_IDENTIFIER)); + /* complete= */ false, new ArraySet<>(), Set.of(fmUniqueId)); createRadioTuner(); mProgramList = mRadioTuner.getDynamicProgramList(TEST_FILTER); registerListCallbacks(/* numCallbacks= */ 1); - mTunerCallback.onProgramListUpdated(FM_RDS_ADD_CHUNK); + mTunerCallback.onProgramListUpdated(FM_DAB_ADD_CHUNK); mTunerCallback.onProgramListUpdated(fmRemovedChunk); verify(mListCallbackMocks[0], CALLBACK_TIMEOUT).onItemRemoved(FM_IDENTIFIER); assertWithMessage("Program info in program list after removing FM id") - .that(mProgramList.toList()).containsExactly(RDS_PROGRAM_INFO); - assertWithMessage("Program info FM identifier") - .that(mProgramList.get(RDS_IDENTIFIER)).isEqualTo(RDS_PROGRAM_INFO); + .that(mProgramList.toList()).containsExactly(DAB_PROGRAM_INFO_1, + DAB_PROGRAM_INFO_2); + } + + @Test + public void onProgramListUpdated_withPartOfDabIdsRemoved_doesNotInvokeCallbacks() + throws Exception { + ProgramList.Chunk dabRemovedChunk1 = new ProgramList.Chunk(/* purge= */ false, + /* complete= */ false, new ArraySet<>(), Set.of(DAB_UNIQUE_IDENTIFIER_1)); + createRadioTuner(); + mProgramList = mRadioTuner.getDynamicProgramList(TEST_FILTER); + registerListCallbacks(/* numCallbacks= */ 1); + mTunerCallback.onProgramListUpdated(FM_DAB_ADD_CHUNK); + + mTunerCallback.onProgramListUpdated(dabRemovedChunk1); + + verify(mListCallbackMocks[0], after(TIMEOUT_MS).never()).onItemRemoved( + DAB_DMB_SID_EXT_IDENTIFIER); + assertWithMessage("Program info in program list after removing part of DAB ids") + .that(mProgramList.toList()).containsExactly(FM_PROGRAM_INFO, DAB_PROGRAM_INFO_2); + } + + @Test + public void onProgramListUpdated_withAllDabIdsRemoved_invokesCallbacks() + throws Exception { + ProgramList.Chunk dabRemovedChunk1 = new ProgramList.Chunk(/* purge= */ false, + /* complete= */ false, new ArraySet<>(), Set.of(DAB_UNIQUE_IDENTIFIER_1)); + ProgramList.Chunk dabRemovedChunk2 = new ProgramList.Chunk(/* purge= */ false, + /* complete= */ false, new ArraySet<>(), Set.of(DAB_UNIQUE_IDENTIFIER_2)); + createRadioTuner(); + mProgramList = mRadioTuner.getDynamicProgramList(TEST_FILTER); + registerListCallbacks(/* numCallbacks= */ 1); + mTunerCallback.onProgramListUpdated(FM_DAB_ADD_CHUNK); + mTunerCallback.onProgramListUpdated(dabRemovedChunk1); + verify(mListCallbackMocks[0], after(TIMEOUT_MS).never()).onItemRemoved( + DAB_DMB_SID_EXT_IDENTIFIER); + + mTunerCallback.onProgramListUpdated(dabRemovedChunk2); + + verify(mListCallbackMocks[0], CALLBACK_TIMEOUT).onItemRemoved(DAB_DMB_SID_EXT_IDENTIFIER); + assertWithMessage("Program info in program list after removing all DAB ids") + .that(mProgramList.toList()).containsExactly(FM_PROGRAM_INFO); } @Test @@ -388,18 +442,18 @@ public final class ProgramListTest { createRadioTuner(); mProgramList = mRadioTuner.getDynamicProgramList(TEST_FILTER); registerListCallbacks(/* numCallbacks= */ 1); - mTunerCallback.onProgramListUpdated(FM_RDS_ADD_CHUNK); + mTunerCallback.onProgramListUpdated(FM_DAB_ADD_CHUNK); mTunerCallback.onProgramListUpdated(purgeChunk); verify(mListCallbackMocks[0], CALLBACK_TIMEOUT).onItemRemoved(FM_IDENTIFIER); - verify(mListCallbackMocks[0], CALLBACK_TIMEOUT).onItemRemoved(RDS_IDENTIFIER); + verify(mListCallbackMocks[0], CALLBACK_TIMEOUT).onItemRemoved(DAB_DMB_SID_EXT_IDENTIFIER); assertWithMessage("Program list after purge chunk applied") .that(mProgramList.toList()).isEmpty(); } @Test - public void onProgramListUpdated_afterProgramListClosed_notInvokeMockedCallbacks() + public void onProgramListUpdated_afterProgramListClosed_notInvokeCallbacks() throws Exception { createRadioTuner(); mProgramList = mRadioTuner.getDynamicProgramList(TEST_FILTER); @@ -407,7 +461,7 @@ public final class ProgramListTest { addOnCompleteListeners(/* numListeners= */ 1); mProgramList.close(); - mTunerCallback.onProgramListUpdated(FM_RDS_ADD_CHUNK); + mTunerCallback.onProgramListUpdated(FM_DAB_ADD_CHUNK); verify(mListCallbackMocks[0], after(TIMEOUT_MS).never()).onItemChanged(any()); verify(mListCallbackMocks[0], never()).onItemChanged(any()); @@ -462,7 +516,7 @@ public final class ProgramListTest { throws Exception { createRadioTuner(); mProgramList = mRadioTuner.getDynamicProgramList(TEST_FILTER); - mTunerCallback.onProgramListUpdated(FM_RDS_ADD_CHUNK); + mTunerCallback.onProgramListUpdated(FM_DAB_ADD_CHUNK); mTunerCallback.onBackgroundScanComplete(); @@ -487,7 +541,7 @@ public final class ProgramListTest { mProgramList = mRadioTuner.getDynamicProgramList(TEST_FILTER); mTunerCallback.onBackgroundScanComplete(); - mTunerCallback.onProgramListUpdated(FM_RDS_ADD_CHUNK); + mTunerCallback.onProgramListUpdated(FM_DAB_ADD_CHUNK); verify(mTunerCallbackMock, CALLBACK_TIMEOUT).onBackgroundScanComplete(); } @@ -512,7 +566,7 @@ public final class ProgramListTest { mock(ProgramList.OnCompleteListener.class); mProgramList.addOnCompleteListener(mExecutor, onCompleteListenerMock); - mTunerCallback.onProgramListUpdated(FM_RDS_ADD_CHUNK); + mTunerCallback.onProgramListUpdated(FM_DAB_ADD_CHUNK); verify(onCompleteListenerMock, CALLBACK_TIMEOUT).onComplete(); } @@ -524,7 +578,7 @@ public final class ProgramListTest { mProgramList = mRadioTuner.getDynamicProgramList(TEST_FILTER); addOnCompleteListeners(numListeners); - mTunerCallback.onProgramListUpdated(FM_RDS_ADD_CHUNK); + mTunerCallback.onProgramListUpdated(FM_DAB_ADD_CHUNK); for (int index = 0; index < numListeners; index++) { verify(mOnCompleteListenerMocks[index], CALLBACK_TIMEOUT).onComplete(); @@ -538,7 +592,7 @@ public final class ProgramListTest { addOnCompleteListeners(/* numListeners= */ 1); mProgramList.removeOnCompleteListener(mOnCompleteListenerMocks[0]); - mTunerCallback.onProgramListUpdated(FM_RDS_ADD_CHUNK); + mTunerCallback.onProgramListUpdated(FM_DAB_ADD_CHUNK); verify(mOnCompleteListenerMocks[0], after(TIMEOUT_MS).never()).onComplete(); } @@ -566,6 +620,13 @@ public final class ProgramListTest { /* vendorInfo= */ null); } + private static RadioManager.ProgramInfo createDabProgramInfo(ProgramSelector selector) { + return new RadioManager.ProgramInfo(selector, selector.getPrimaryId(), + DAB_ENSEMBLE_IDENTIFIER, /* relatedContents= */ null, /* infoFlags= */ 0, + /* signalQuality= */ 1, new RadioMetadata.Builder().build(), + /* vendorInfo= */ null); + } + private void createRadioTuner() throws Exception { mApplicationInfo.targetSdkVersion = TEST_TARGET_SDK_VERSION; when(mContextMock.getApplicationInfo()).thenReturn(mApplicationInfo); diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java index 6c701920bd51..4f469bb957d4 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java @@ -25,6 +25,7 @@ import android.hardware.radio.ProgramList; import android.hardware.radio.ProgramSelector; import android.hardware.radio.RadioManager; import android.hardware.radio.RadioMetadata; +import android.hardware.radio.UniqueProgramIdentifier; import android.os.RemoteException; import android.util.ArrayMap; import android.util.ArraySet; @@ -149,12 +150,12 @@ final class AidlTestUtils { static ProgramList.Chunk makeChunk(boolean purge, boolean complete, List<RadioManager.ProgramInfo> modified, - List<ProgramSelector.Identifier> removed) throws RemoteException { + List<UniqueProgramIdentifier> removed) throws RemoteException { ArraySet<RadioManager.ProgramInfo> modifiedSet = new ArraySet<>(); if (modified != null) { modifiedSet.addAll(modified); } - ArraySet<ProgramSelector.Identifier> removedSet = new ArraySet<>(); + ArraySet<UniqueProgramIdentifier> removedSet = new ArraySet<>(); if (removed != null) { removedSet.addAll(removed); } diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java index 2ef923d1339a..89b91cf27b38 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java @@ -25,7 +25,6 @@ import android.hardware.broadcastradio.DabTableEntry; import android.hardware.broadcastradio.IdentifierType; import android.hardware.broadcastradio.ProgramIdentifier; import android.hardware.broadcastradio.ProgramInfo; -import android.hardware.broadcastradio.ProgramListChunk; import android.hardware.broadcastradio.Properties; import android.hardware.broadcastradio.Result; import android.hardware.broadcastradio.VendorKeyValue; @@ -33,6 +32,7 @@ import android.hardware.radio.Announcement; import android.hardware.radio.ProgramList; import android.hardware.radio.ProgramSelector; import android.hardware.radio.RadioManager; +import android.hardware.radio.UniqueProgramIdentifier; import android.os.ServiceSpecificException; import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; @@ -103,12 +103,6 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase { private static final ProgramIdentifier TEST_HAL_DAB_FREQUENCY_ID = AidlTestUtils.makeHalIdentifier(IdentifierType.DAB_FREQUENCY_KHZ, TEST_DAB_FREQUENCY_VALUE); - private static final ProgramIdentifier TEST_HAL_FM_FREQUENCY_ID = - AidlTestUtils.makeHalIdentifier(IdentifierType.AMFM_FREQUENCY_KHZ, - TEST_FM_FREQUENCY_VALUE); - private static final ProgramIdentifier TEST_HAL_VENDOR_ID = - AidlTestUtils.makeHalIdentifier(IdentifierType.VENDOR_START, - TEST_VENDOR_ID_VALUE); private static final ProgramSelector TEST_DAB_SELECTOR = new ProgramSelector( ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_SID_EXT_ID, @@ -117,6 +111,12 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase { private static final ProgramSelector TEST_FM_SELECTOR = AidlTestUtils.makeFmSelector(TEST_FM_FREQUENCY_VALUE); + private static final UniqueProgramIdentifier TEST_DAB_UNIQUE_ID = new UniqueProgramIdentifier( + TEST_DAB_SELECTOR); + + private static final UniqueProgramIdentifier TEST_VENDOR_UNIQUE_ID = + new UniqueProgramIdentifier(TEST_VENDOR_ID); + private static final int TEST_ENABLED_TYPE = Announcement.TYPE_EMERGENCY; private static final int TEST_ANNOUNCEMENT_FREQUENCY = FM_LOWER_LIMIT + FM_SPACING; @@ -326,57 +326,6 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase { } @Test - public void chunkFromHalProgramListChunk_withValidChunk() { - boolean purge = false; - boolean complete = true; - android.hardware.broadcastradio.ProgramSelector halDabSelector = - AidlTestUtils.makeHalSelector(TEST_HAL_DAB_SID_EXT_ID, new ProgramIdentifier[]{ - TEST_HAL_DAB_ENSEMBLE_ID, TEST_HAL_DAB_FREQUENCY_ID}); - ProgramInfo halDabInfo = AidlTestUtils.makeHalProgramInfo(halDabSelector, - TEST_HAL_DAB_SID_EXT_ID, TEST_HAL_DAB_FREQUENCY_ID, TEST_SIGNAL_QUALITY); - RadioManager.ProgramInfo dabInfo = - ConversionUtils.programInfoFromHalProgramInfo(halDabInfo); - ProgramListChunk halChunk = AidlTestUtils.makeHalChunk(purge, complete, - new ProgramInfo[]{halDabInfo}, - new ProgramIdentifier[]{TEST_HAL_VENDOR_ID, TEST_HAL_FM_FREQUENCY_ID}); - - ProgramList.Chunk chunk = ConversionUtils.chunkFromHalProgramListChunk(halChunk); - - expect.withMessage("Purged state of the converted valid program list chunk") - .that(chunk.isPurge()).isEqualTo(purge); - expect.withMessage("Completion state of the converted valid program list chunk") - .that(chunk.isComplete()).isEqualTo(complete); - expect.withMessage("Modified program info in the converted valid program list chunk") - .that(chunk.getModified()).containsExactly(dabInfo); - expect.withMessage("Removed program ides in the converted valid program list chunk") - .that(chunk.getRemoved()).containsExactly(TEST_VENDOR_ID, TEST_FM_FREQUENCY_ID); - } - - @Test - public void chunkFromHalProgramListChunk_withInvalidModifiedProgramInfo() { - boolean purge = true; - boolean complete = false; - android.hardware.broadcastradio.ProgramSelector halDabSelector = - AidlTestUtils.makeHalSelector(TEST_HAL_DAB_SID_EXT_ID, new ProgramIdentifier[]{ - TEST_HAL_DAB_ENSEMBLE_ID, TEST_HAL_DAB_FREQUENCY_ID}); - ProgramInfo halDabInfo = AidlTestUtils.makeHalProgramInfo(halDabSelector, - TEST_HAL_DAB_SID_EXT_ID, TEST_HAL_DAB_ENSEMBLE_ID, TEST_SIGNAL_QUALITY); - ProgramListChunk halChunk = AidlTestUtils.makeHalChunk(purge, complete, - new ProgramInfo[]{halDabInfo}, new ProgramIdentifier[]{TEST_HAL_FM_FREQUENCY_ID}); - - ProgramList.Chunk chunk = ConversionUtils.chunkFromHalProgramListChunk(halChunk); - - expect.withMessage("Purged state of the converted invalid program list chunk") - .that(chunk.isPurge()).isEqualTo(purge); - expect.withMessage("Completion state of the converted invalid program list chunk") - .that(chunk.isComplete()).isEqualTo(complete); - expect.withMessage("Modified program info in the converted invalid program list chunk") - .that(chunk.getModified()).isEmpty(); - expect.withMessage("Removed program ids in the converted invalid program list chunk") - .that(chunk.getRemoved()).containsExactly(TEST_FM_FREQUENCY_ID); - } - - @Test public void programSelectorMeetsSdkVersionRequirement_withLowerVersionId_returnsFalse() { expect.withMessage("Selector %s without required SDK version", TEST_DAB_SELECTOR) .that(ConversionUtils.programSelectorMeetsSdkVersionRequirement(TEST_DAB_SELECTOR, @@ -418,7 +367,7 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase { TEST_SIGNAL_QUALITY); ProgramList.Chunk chunk = new ProgramList.Chunk(/* purge= */ true, /* complete= */ true, Set.of(dabProgramInfo, fmProgramInfo), - Set.of(TEST_DAB_SID_EXT_ID, TEST_DAB_ENSEMBLE_ID, TEST_VENDOR_ID)); + Set.of(TEST_DAB_UNIQUE_ID, TEST_VENDOR_UNIQUE_ID)); ProgramList.Chunk convertedChunk = ConversionUtils.convertChunkToTargetSdkVersion(chunk, T_APP_UID); @@ -434,8 +383,7 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase { .that(convertedChunk.getModified()).containsExactly(fmProgramInfo); expect.withMessage( "Removed program ids in the converted program list chunk with lower SDK version") - .that(convertedChunk.getRemoved()) - .containsExactly(TEST_DAB_ENSEMBLE_ID, TEST_VENDOR_ID); + .that(convertedChunk.getRemoved()).containsExactly(TEST_VENDOR_UNIQUE_ID); } @Test @@ -446,7 +394,7 @@ public final class ConversionUtilsTest extends ExtendedRadioMockitoTestCase { TEST_SIGNAL_QUALITY); ProgramList.Chunk chunk = new ProgramList.Chunk(/* purge= */ true, /* complete= */ true, Set.of(dabProgramInfo, fmProgramInfo), - Set.of(TEST_DAB_SID_EXT_ID, TEST_DAB_ENSEMBLE_ID, TEST_VENDOR_ID)); + Set.of(TEST_DAB_UNIQUE_ID, TEST_VENDOR_UNIQUE_ID)); ProgramList.Chunk convertedChunk = ConversionUtils.convertChunkToTargetSdkVersion(chunk, U_APP_UID); diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ProgramInfoCacheTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ProgramInfoCacheTest.java index d54397e07a63..ce27bc177769 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ProgramInfoCacheTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ProgramInfoCacheTest.java @@ -22,6 +22,7 @@ import android.hardware.broadcastradio.ProgramListChunk; import android.hardware.radio.ProgramList; import android.hardware.radio.ProgramSelector; import android.hardware.radio.RadioManager; +import android.hardware.radio.UniqueProgramIdentifier; import android.os.RemoteException; import android.util.ArraySet; @@ -32,6 +33,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; +import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -43,6 +45,9 @@ public class ProgramInfoCacheTest { private static final int TEST_SIGNAL_QUALITY = 90; + private static final int TEST_MAX_NUM_MODIFIED_PER_CHUNK = 2; + private static final int TEST_MAX_NUM_REMOVED_PER_CHUNK = 2; + private static final ProgramSelector.Identifier TEST_FM_FREQUENCY_ID = new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, /* value= */ 88_500); @@ -58,6 +63,8 @@ public class ProgramInfoCacheTest { private static final ProgramSelector.Identifier TEST_AM_FREQUENCY_ID = new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, /* value= */ 1_700); + private static final UniqueProgramIdentifier TEST_AM_UNIQUE_ID = new UniqueProgramIdentifier( + TEST_AM_FREQUENCY_ID); private static final RadioManager.ProgramInfo TEST_AM_INFO = AidlTestUtils.makeProgramInfo( AidlTestUtils.makeProgramSelector(ProgramSelector.PROGRAM_TYPE_FM, TEST_AM_FREQUENCY_ID), TEST_AM_FREQUENCY_ID, TEST_AM_FREQUENCY_ID, @@ -66,6 +73,8 @@ public class ProgramInfoCacheTest { private static final ProgramSelector.Identifier TEST_RDS_PI_ID = new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_RDS_PI, /* value= */ 15_019); + private static final UniqueProgramIdentifier TEST_RDS_PI_UNIQUE_ID = + new UniqueProgramIdentifier(TEST_RDS_PI_ID); private static final RadioManager.ProgramInfo TEST_RDS_INFO = AidlTestUtils.makeProgramInfo( AidlTestUtils.makeProgramSelector(ProgramSelector.PROGRAM_TYPE_FM, TEST_RDS_PI_ID), TEST_RDS_PI_ID, new ProgramSelector.Identifier( @@ -81,11 +90,27 @@ public class ProgramInfoCacheTest { private static final ProgramSelector.Identifier TEST_DAB_FREQUENCY_ID = new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, /* value= */ 220_352); - private static final RadioManager.ProgramInfo TEST_DAB_INFO = AidlTestUtils.makeProgramInfo( - new ProgramSelector(ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_DMB_SID_EXT_ID, - new ProgramSelector.Identifier[]{TEST_DAB_FREQUENCY_ID, TEST_DAB_ENSEMBLE_ID}, - /* vendorIds= */ null), TEST_DAB_DMB_SID_EXT_ID, TEST_DAB_FREQUENCY_ID, - TEST_SIGNAL_QUALITY); + private static final ProgramSelector.Identifier TEST_DAB_FREQUENCY_ID_ALTERNATIVE = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, + /* value= */ 220_064); + private static final ProgramSelector TEST_DAB_SELECTOR = new ProgramSelector( + ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_DMB_SID_EXT_ID, + new ProgramSelector.Identifier[]{TEST_DAB_FREQUENCY_ID, TEST_DAB_ENSEMBLE_ID}, + /* vendorIds= */ null); + private static final ProgramSelector TEST_DAB_SELECTOR_ALTERNATIVE = new ProgramSelector( + ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_DMB_SID_EXT_ID, + new ProgramSelector.Identifier[]{TEST_DAB_FREQUENCY_ID_ALTERNATIVE, + TEST_DAB_ENSEMBLE_ID}, /* vendorIds= */ null); + private static final UniqueProgramIdentifier TEST_DAB_UNIQUE_ID = new UniqueProgramIdentifier( + TEST_DAB_SELECTOR); + private static final UniqueProgramIdentifier TEST_DAB_UNIQUE_ID_ALTERNATIVE = + new UniqueProgramIdentifier(TEST_DAB_SELECTOR_ALTERNATIVE); + private static final RadioManager.ProgramInfo TEST_DAB_INFO = + AidlTestUtils.makeProgramInfo(TEST_DAB_SELECTOR, TEST_DAB_DMB_SID_EXT_ID, + TEST_DAB_FREQUENCY_ID, TEST_SIGNAL_QUALITY); + private static final RadioManager.ProgramInfo TEST_DAB_INFO_ALTERNATIVE = + AidlTestUtils.makeProgramInfo(TEST_DAB_SELECTOR_ALTERNATIVE, TEST_DAB_DMB_SID_EXT_ID, + TEST_DAB_FREQUENCY_ID_ALTERNATIVE, TEST_SIGNAL_QUALITY); private static final ProgramSelector.Identifier TEST_VENDOR_ID = new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_VENDOR_START, @@ -95,8 +120,8 @@ public class ProgramInfoCacheTest { TEST_VENDOR_ID), TEST_VENDOR_ID, TEST_VENDOR_ID, TEST_SIGNAL_QUALITY); private static final ProgramInfoCache FULL_PROGRAM_INFO_CACHE = new ProgramInfoCache( - /* filter= */ null, /* complete= */ true, - TEST_FM_INFO, TEST_AM_INFO, TEST_RDS_INFO, TEST_DAB_INFO, TEST_VENDOR_INFO); + /* filter= */ null, /* complete= */ true, TEST_FM_INFO, TEST_AM_INFO, TEST_RDS_INFO, + TEST_DAB_INFO, TEST_DAB_INFO_ALTERNATIVE, TEST_VENDOR_INFO); @Rule public final Expect expect = Expect.create(); @@ -163,6 +188,22 @@ public class ProgramInfoCacheTest { } @Test + public void updateFromHalProgramListChunk_withInvalidChunk() { + RadioManager.ProgramInfo invalidDabInfo = AidlTestUtils.makeProgramInfo(TEST_DAB_SELECTOR, + TEST_DAB_DMB_SID_EXT_ID, TEST_DAB_ENSEMBLE_ID, TEST_SIGNAL_QUALITY); + ProgramInfoCache cache = new ProgramInfoCache(/* filter= */ null, + /* complete= */ false); + ProgramListChunk chunk = AidlTestUtils.makeHalChunk(/* purge= */ false, + /* complete= */ true, new ProgramInfo[]{AidlTestUtils.programInfoToHalProgramInfo( + invalidDabInfo)}, new ProgramIdentifier[]{}); + + cache.updateFromHalProgramListChunk(chunk); + + expect.withMessage("Program cache updated with invalid chunk") + .that(cache.toProgramInfoList()).isEmpty(); + } + + @Test public void filterAndUpdateFromInternal_withNullFilter() { ProgramInfoCache cache = new ProgramInfoCache(/* filter= */ null, /* complete= */ true); @@ -172,7 +213,7 @@ public class ProgramInfoCacheTest { expect.withMessage("Program cache filtered by null filter") .that(cache.toProgramInfoList()) .containsExactly(TEST_FM_INFO, TEST_AM_INFO, TEST_RDS_INFO, TEST_DAB_INFO, - TEST_VENDOR_INFO); + TEST_DAB_INFO_ALTERNATIVE, TEST_VENDOR_INFO); } @Test @@ -186,21 +227,21 @@ public class ProgramInfoCacheTest { expect.withMessage("Program cache filtered by empty filter") .that(cache.toProgramInfoList()) .containsExactly(TEST_FM_INFO, TEST_AM_INFO, TEST_RDS_INFO, TEST_DAB_INFO, - TEST_VENDOR_INFO); + TEST_DAB_INFO_ALTERNATIVE, TEST_VENDOR_INFO); } @Test public void filterAndUpdateFromInternal_withFilterByIdentifierType() { ProgramInfoCache cache = new ProgramInfoCache( new ProgramList.Filter(Set.of(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, - ProgramSelector.IDENTIFIER_TYPE_RDS_PI), new ArraySet<>(), + ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT), new ArraySet<>(), /* includeCategories= */ true, /* excludeModifications= */ false)); cache.filterAndUpdateFromInternal(FULL_PROGRAM_INFO_CACHE, /* purge= */ false); expect.withMessage("Program cache filtered by identifier type") - .that(cache.toProgramInfoList()) - .containsExactly(TEST_FM_INFO, TEST_AM_INFO, TEST_RDS_INFO); + .that(cache.toProgramInfoList()).containsExactly(TEST_FM_INFO, TEST_AM_INFO, + TEST_DAB_INFO, TEST_DAB_INFO_ALTERNATIVE); } @Test @@ -208,20 +249,60 @@ public class ProgramInfoCacheTest { ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter( new ArraySet<>(), Set.of(TEST_FM_FREQUENCY_ID, TEST_DAB_DMB_SID_EXT_ID), /* includeCategories= */ true, /* excludeModifications= */ false)); - int maxNumModifiedPerChunk = 2; - int maxNumRemovedPerChunk = 2; List<ProgramList.Chunk> programListChunks = cache.filterAndUpdateFromInternal( - FULL_PROGRAM_INFO_CACHE, /* purge= */ true, maxNumModifiedPerChunk, - maxNumRemovedPerChunk); + FULL_PROGRAM_INFO_CACHE, /* purge= */ false, TEST_MAX_NUM_MODIFIED_PER_CHUNK, + TEST_MAX_NUM_REMOVED_PER_CHUNK); expect.withMessage("Program cache filtered by identifier") - .that(cache.toProgramInfoList()).containsExactly(TEST_FM_INFO, TEST_DAB_INFO); + .that(cache.toProgramInfoList()).containsExactly(TEST_FM_INFO, TEST_DAB_INFO, + TEST_DAB_INFO_ALTERNATIVE); + verifyChunkListPurge(programListChunks, /* purge= */ true); + verifyChunkListComplete(programListChunks, cache.isComplete()); + verifyChunkListModified(programListChunks, TEST_MAX_NUM_MODIFIED_PER_CHUNK, TEST_FM_INFO, + TEST_DAB_INFO, TEST_DAB_INFO_ALTERNATIVE); + verifyChunkListRemoved(programListChunks, TEST_MAX_NUM_REMOVED_PER_CHUNK); + } + + @Test + public void filterAndUpdateFromInternal_withPurging() { + ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(new ArraySet<>(), + new ArraySet<>(), /* includeCategories= */ true, /* excludeModifications= */ false), + /* complete= */ true, TEST_RDS_INFO, TEST_DAB_INFO); + ProgramInfoCache otherCache = new ProgramInfoCache(/* filter= */ null, /* complete= */ true, + TEST_FM_INFO, TEST_RDS_INFO, TEST_DAB_INFO_ALTERNATIVE); + + List<ProgramList.Chunk> programListChunks = cache.filterAndUpdateFromInternal(otherCache, + /* purge= */ true, TEST_MAX_NUM_MODIFIED_PER_CHUNK, TEST_MAX_NUM_REMOVED_PER_CHUNK); + + expect.withMessage("Program cache filtered with purging").that(cache.toProgramInfoList()) + .containsExactly(TEST_FM_INFO, TEST_RDS_INFO, TEST_DAB_INFO_ALTERNATIVE); verifyChunkListPurge(programListChunks, /* purge= */ true); - verifyChunkListComplete(programListChunks, FULL_PROGRAM_INFO_CACHE.isComplete()); + verifyChunkListModified(programListChunks, TEST_MAX_NUM_MODIFIED_PER_CHUNK, TEST_FM_INFO, + TEST_RDS_INFO, TEST_DAB_INFO_ALTERNATIVE); + verifyChunkListRemoved(programListChunks, TEST_MAX_NUM_REMOVED_PER_CHUNK); + } + + @Test + public void filterAndUpdateFromInternal_withoutPurging() { + ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(new ArraySet<>(), + new ArraySet<>(), /* includeCategories= */ true, /* excludeModifications= */ false), + /* complete= */ true, TEST_RDS_INFO, TEST_DAB_INFO); + ProgramInfoCache otherCache = new ProgramInfoCache(/* filter= */ null, /* complete= */ true, + TEST_FM_INFO, TEST_RDS_INFO, TEST_DAB_INFO_ALTERNATIVE); + int maxNumModifiedPerChunk = 1; + + List<ProgramList.Chunk> programListChunks = cache.filterAndUpdateFromInternal(otherCache, + /* purge= */ false, maxNumModifiedPerChunk, TEST_MAX_NUM_REMOVED_PER_CHUNK); + + expect.withMessage("Program cache filtered without puring").that(cache.toProgramInfoList()) + .containsExactly(TEST_FM_INFO, TEST_RDS_INFO, TEST_DAB_INFO_ALTERNATIVE); + verifyChunkListPurge(programListChunks, /* purge= */ false); + verifyChunkListComplete(programListChunks, cache.isComplete()); verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_FM_INFO, - TEST_DAB_INFO); - verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk); + TEST_DAB_INFO_ALTERNATIVE); + verifyChunkListRemoved(programListChunks, TEST_MAX_NUM_REMOVED_PER_CHUNK, + TEST_DAB_UNIQUE_ID); } @Test @@ -230,20 +311,19 @@ public class ProgramInfoCacheTest { new ArraySet<>(), /* includeCategories= */ false, /* excludeModifications= */ false)); int maxNumModifiedPerChunk = 3; - int maxNumRemovedPerChunk = 2; List<ProgramList.Chunk> programListChunks = cache.filterAndUpdateFromInternal( FULL_PROGRAM_INFO_CACHE, /* purge= */ false, maxNumModifiedPerChunk, - maxNumRemovedPerChunk); + TEST_MAX_NUM_REMOVED_PER_CHUNK); expect.withMessage("Program cache filtered by excluding categories") - .that(cache.toProgramInfoList()) - .containsExactly(TEST_FM_INFO, TEST_AM_INFO, TEST_RDS_INFO, TEST_DAB_INFO); + .that(cache.toProgramInfoList()).containsExactly(TEST_FM_INFO, TEST_AM_INFO, + TEST_RDS_INFO, TEST_DAB_INFO, TEST_DAB_INFO_ALTERNATIVE); verifyChunkListPurge(programListChunks, /* purge= */ true); - verifyChunkListComplete(programListChunks, FULL_PROGRAM_INFO_CACHE.isComplete()); + verifyChunkListComplete(programListChunks, cache.isComplete()); verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_FM_INFO, - TEST_AM_INFO, TEST_RDS_INFO, TEST_DAB_INFO); - verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk); + TEST_AM_INFO, TEST_RDS_INFO, TEST_DAB_INFO, TEST_DAB_INFO_ALTERNATIVE); + verifyChunkListRemoved(programListChunks, TEST_MAX_NUM_REMOVED_PER_CHUNK); } @Test @@ -254,21 +334,21 @@ public class ProgramInfoCacheTest { ProgramInfoCache cache = new ProgramInfoCache(filterExcludingModifications, /* complete= */ true, TEST_FM_INFO, TEST_RDS_INFO, TEST_AM_INFO, TEST_DAB_INFO); ProgramInfoCache halCache = new ProgramInfoCache(/* filter= */ null, /* complete= */ false, - TEST_FM_INFO_MODIFIED, TEST_VENDOR_INFO); - int maxNumModifiedPerChunk = 2; - int maxNumRemovedPerChunk = 2; + TEST_FM_INFO_MODIFIED, TEST_DAB_INFO_ALTERNATIVE, TEST_VENDOR_INFO); List<ProgramList.Chunk> programListChunks = cache.filterAndUpdateFromInternal(halCache, - /* purge= */ false, maxNumModifiedPerChunk, maxNumRemovedPerChunk); + /* purge= */ false, TEST_MAX_NUM_MODIFIED_PER_CHUNK, + TEST_MAX_NUM_REMOVED_PER_CHUNK); expect.withMessage("Program cache filtered by excluding modifications") .that(cache.toProgramInfoList()) - .containsExactly(TEST_FM_INFO, TEST_VENDOR_INFO); + .containsExactly(TEST_FM_INFO, TEST_DAB_INFO_ALTERNATIVE, TEST_VENDOR_INFO); verifyChunkListPurge(programListChunks, /* purge= */ false); verifyChunkListComplete(programListChunks, halCache.isComplete()); - verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_VENDOR_INFO); - verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk, TEST_RDS_PI_ID, - TEST_AM_FREQUENCY_ID, TEST_DAB_DMB_SID_EXT_ID); + verifyChunkListModified(programListChunks, TEST_MAX_NUM_MODIFIED_PER_CHUNK, + TEST_VENDOR_INFO, TEST_DAB_INFO_ALTERNATIVE); + verifyChunkListRemoved(programListChunks, TEST_MAX_NUM_REMOVED_PER_CHUNK, + TEST_RDS_PI_UNIQUE_ID, TEST_AM_UNIQUE_ID, TEST_DAB_UNIQUE_ID); } @Test @@ -276,69 +356,88 @@ public class ProgramInfoCacheTest { ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(), /* includeCategories= */ true, /* excludeModifications= */ false), - /* complete= */ true, TEST_FM_INFO, TEST_RDS_INFO); + /* complete= */ true, TEST_FM_INFO, TEST_RDS_INFO, TEST_DAB_INFO); ProgramInfoCache halCache = new ProgramInfoCache(/* filter= */ null, /* complete= */ false, - TEST_FM_INFO_MODIFIED, TEST_DAB_INFO, TEST_VENDOR_INFO); - int maxNumModifiedPerChunk = 2; - int maxNumRemovedPerChunk = 2; + TEST_FM_INFO_MODIFIED, TEST_DAB_INFO_ALTERNATIVE, TEST_VENDOR_INFO); List<ProgramList.Chunk> programListChunks = cache.filterAndUpdateFromInternal(halCache, - /* purge= */ true, maxNumModifiedPerChunk, maxNumRemovedPerChunk); + /* purge= */ true, TEST_MAX_NUM_MODIFIED_PER_CHUNK, TEST_MAX_NUM_REMOVED_PER_CHUNK); expect.withMessage("Purged program cache").that(cache.toProgramInfoList()) - .containsExactly(TEST_FM_INFO_MODIFIED, TEST_DAB_INFO, TEST_VENDOR_INFO); + .containsExactly(TEST_FM_INFO_MODIFIED, TEST_DAB_INFO_ALTERNATIVE, + TEST_VENDOR_INFO); verifyChunkListPurge(programListChunks, /* purge= */ true); verifyChunkListComplete(programListChunks, halCache.isComplete()); - verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_FM_INFO_MODIFIED, - TEST_DAB_INFO, TEST_VENDOR_INFO); - verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk); + verifyChunkListModified(programListChunks, TEST_MAX_NUM_MODIFIED_PER_CHUNK, + TEST_FM_INFO_MODIFIED, TEST_DAB_INFO_ALTERNATIVE, TEST_VENDOR_INFO); + verifyChunkListRemoved(programListChunks, TEST_MAX_NUM_REMOVED_PER_CHUNK); } @Test - public void filterAndApplyChunkInternal_withPurgingIncompleteChunk() throws RemoteException { + public void filterAndApplyChunkInternal_withPurgingAndIncompleteChunk() throws RemoteException { ProgramInfoCache cache = new ProgramInfoCache(/* filter= */ null, - /* complete= */ false, TEST_FM_INFO, TEST_DAB_INFO); - ProgramList.Chunk chunk = AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ false, - List.of(TEST_FM_INFO_MODIFIED, TEST_RDS_INFO, TEST_VENDOR_INFO), - List.of(TEST_DAB_DMB_SID_EXT_ID)); - int maxNumModifiedPerChunk = 2; - int maxNumRemovedPerChunk = 2; + /* complete= */ false, TEST_FM_INFO, TEST_RDS_INFO, TEST_DAB_INFO); + ProgramListChunk halChunk = AidlTestUtils.makeHalChunk(/* purge= */ true, + /* complete= */ false, List.of(TEST_FM_INFO_MODIFIED, + TEST_DAB_INFO_ALTERNATIVE, TEST_VENDOR_INFO), new ArrayList<>()); - List<ProgramList.Chunk> programListChunks = cache.filterAndApplyChunkInternal(chunk, - maxNumModifiedPerChunk, maxNumRemovedPerChunk); + List<ProgramList.Chunk> programListChunks = cache.filterAndApplyChunkInternal(halChunk, + TEST_MAX_NUM_MODIFIED_PER_CHUNK, TEST_MAX_NUM_REMOVED_PER_CHUNK); - expect.withMessage("Program cache applied with non-purging and complete chunk") - .that(cache.toProgramInfoList()) - .containsExactly(TEST_FM_INFO_MODIFIED, TEST_RDS_INFO, TEST_VENDOR_INFO); + expect.withMessage("Program cache applied with purge-enabled and complete chunk") + .that(cache.toProgramInfoList()).containsExactly(TEST_FM_INFO_MODIFIED, + TEST_DAB_INFO_ALTERNATIVE, TEST_VENDOR_INFO); verifyChunkListPurge(programListChunks, /* purge= */ true); verifyChunkListComplete(programListChunks, /* complete= */ false); - verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_FM_INFO_MODIFIED, - TEST_RDS_INFO, TEST_VENDOR_INFO); - verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk); + verifyChunkListModified(programListChunks, TEST_MAX_NUM_MODIFIED_PER_CHUNK, + TEST_FM_INFO_MODIFIED, TEST_DAB_INFO_ALTERNATIVE, TEST_VENDOR_INFO); + verifyChunkListRemoved(programListChunks, TEST_MAX_NUM_REMOVED_PER_CHUNK); } @Test - public void filterAndApplyChunk_withNonPurgingCompleteChunk() throws RemoteException { - ProgramInfoCache cache = new ProgramInfoCache(/* filter= */ null, - /* complete= */ false, TEST_FM_INFO, TEST_RDS_INFO, TEST_AM_INFO, TEST_DAB_INFO); - ProgramList.Chunk chunk = AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true, - List.of(TEST_FM_INFO_MODIFIED, TEST_VENDOR_INFO), + public void filterAndApplyChunk_withNonPurgingAndIncompleteChunk() throws RemoteException { + ProgramInfoCache cache = new ProgramInfoCache(/* filter= */ null, /* complete= */ false, + TEST_FM_INFO, TEST_RDS_INFO, TEST_AM_INFO, TEST_DAB_INFO); + ProgramListChunk halChunk = AidlTestUtils.makeHalChunk(/* purge= */ false, + /* complete= */ false, List.of(TEST_FM_INFO_MODIFIED, TEST_DAB_INFO_ALTERNATIVE, + TEST_VENDOR_INFO), List.of(TEST_RDS_PI_ID, TEST_AM_FREQUENCY_ID)); + + List<ProgramList.Chunk> programListChunks = cache.filterAndApplyChunkInternal(halChunk, + TEST_MAX_NUM_MODIFIED_PER_CHUNK, TEST_MAX_NUM_REMOVED_PER_CHUNK); + + expect.withMessage("Program cache applied with non-purging and incomplete chunk") + .that(cache.toProgramInfoList()).containsExactly(TEST_DAB_INFO, + TEST_DAB_INFO_ALTERNATIVE, TEST_FM_INFO_MODIFIED, TEST_VENDOR_INFO); + verifyChunkListPurge(programListChunks, /* purge= */ false); + verifyChunkListComplete(programListChunks, /* complete= */ false); + verifyChunkListModified(programListChunks, TEST_MAX_NUM_MODIFIED_PER_CHUNK, + TEST_FM_INFO_MODIFIED, TEST_DAB_INFO_ALTERNATIVE, TEST_VENDOR_INFO); + verifyChunkListRemoved(programListChunks, TEST_MAX_NUM_REMOVED_PER_CHUNK, + TEST_RDS_PI_UNIQUE_ID, TEST_AM_UNIQUE_ID); + } + + @Test + public void filterAndApplyChunk_withNonPurgingAndCompleteChunk() throws RemoteException { + ProgramInfoCache cache = new ProgramInfoCache(/* filter= */ null, /* complete= */ false, + TEST_FM_INFO, TEST_RDS_INFO, TEST_AM_INFO, TEST_DAB_INFO, + TEST_DAB_INFO_ALTERNATIVE); + ProgramListChunk halChunk = AidlTestUtils.makeHalChunk(/* purge= */ false, + /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED, TEST_VENDOR_INFO), List.of(TEST_RDS_PI_ID, TEST_AM_FREQUENCY_ID, TEST_DAB_DMB_SID_EXT_ID)); - int maxNumModifiedPerChunk = 2; - int maxNumRemovedPerChunk = 2; - List<ProgramList.Chunk> programListChunks = cache.filterAndApplyChunkInternal(chunk, - maxNumModifiedPerChunk, maxNumRemovedPerChunk); + List<ProgramList.Chunk> programListChunks = cache.filterAndApplyChunkInternal(halChunk, + TEST_MAX_NUM_MODIFIED_PER_CHUNK, TEST_MAX_NUM_REMOVED_PER_CHUNK); - expect.withMessage("Program cache applied with purge-enabled complete chunk") + expect.withMessage("Program cache applied with non-purging and complete chunk") .that(cache.toProgramInfoList()) .containsExactly(TEST_FM_INFO_MODIFIED, TEST_VENDOR_INFO); verifyChunkListPurge(programListChunks, /* purge= */ false); verifyChunkListComplete(programListChunks, /* complete= */ true); - verifyChunkListModified(programListChunks, maxNumModifiedPerChunk, TEST_FM_INFO_MODIFIED, - TEST_VENDOR_INFO); - verifyChunkListRemoved(programListChunks, maxNumRemovedPerChunk, TEST_RDS_PI_ID, - TEST_AM_FREQUENCY_ID, TEST_DAB_DMB_SID_EXT_ID); + verifyChunkListModified(programListChunks, TEST_MAX_NUM_MODIFIED_PER_CHUNK, + TEST_FM_INFO_MODIFIED, TEST_VENDOR_INFO); + verifyChunkListRemoved(programListChunks, TEST_MAX_NUM_REMOVED_PER_CHUNK, + TEST_RDS_PI_UNIQUE_ID, TEST_AM_UNIQUE_ID, TEST_DAB_UNIQUE_ID, + TEST_DAB_UNIQUE_ID_ALTERNATIVE); } private void verifyChunkListPurge(List<ProgramList.Chunk> chunks, boolean purge) { @@ -387,17 +486,17 @@ public class ProgramInfoCacheTest { .that(actualSet).containsExactlyElementsIn(expectedProgramInfos); } - private void verifyChunkListRemoved(List<ProgramList.Chunk> chunks, - int maxRemovedPerChunk, ProgramSelector.Identifier... expectedIdentifiers) { + private void verifyChunkListRemoved(List<ProgramList.Chunk> chunks, int maxRemovedPerChunk, + UniqueProgramIdentifier... expectedIdentifiers) { if (chunks.isEmpty()) { expect.withMessage("Empty program info list") .that(expectedIdentifiers.length).isEqualTo(0); return; } - ArraySet<ProgramSelector.Identifier> actualSet = new ArraySet<>(); + ArraySet<UniqueProgramIdentifier> actualSet = new ArraySet<>(); for (int i = 0; i < chunks.size(); i++) { - Set<ProgramSelector.Identifier> chunkRemoved = chunks.get(i).getRemoved(); + Set<UniqueProgramIdentifier> chunkRemoved = chunks.get(i).getRemoved(); actualSet.addAll(chunkRemoved); expect.withMessage("Chunk %s removed identifier array size ", i) diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java index 84aa86472e81..a1952282dd0b 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java @@ -18,8 +18,6 @@ package com.android.server.broadcastradio.aidl; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; -import static com.google.common.truth.Truth.assertWithMessage; - import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -47,6 +45,7 @@ import android.hardware.radio.ProgramList; import android.hardware.radio.ProgramSelector; import android.hardware.radio.RadioManager; import android.hardware.radio.RadioTuner; +import android.hardware.radio.UniqueProgramIdentifier; import android.os.Binder; import android.os.ParcelableException; import android.os.RemoteException; @@ -59,13 +58,18 @@ import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase; import com.android.server.broadcastradio.RadioServiceUserController; +import com.google.common.truth.Expect; + import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.verification.VerificationWithTimeout; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Set; @@ -94,10 +98,6 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { private static final ProgramSelector.Identifier TEST_FM_FREQUENCY_ID = new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, /* value= */ 88_500); - private static final ProgramSelector.Identifier TEST_RDS_PI_ID = - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_RDS_PI, - /* value= */ 15_019); - private static final RadioManager.ProgramInfo TEST_FM_INFO = AidlTestUtils.makeProgramInfo( AidlTestUtils.makeProgramSelector(ProgramSelector.PROGRAM_TYPE_FM, TEST_FM_FREQUENCY_ID), TEST_FM_FREQUENCY_ID, TEST_FM_FREQUENCY_ID, @@ -106,11 +106,37 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { AidlTestUtils.makeProgramInfo(AidlTestUtils.makeProgramSelector( ProgramSelector.PROGRAM_TYPE_FM, TEST_FM_FREQUENCY_ID), TEST_FM_FREQUENCY_ID, TEST_FM_FREQUENCY_ID, /* signalQuality= */ 100); - private static final RadioManager.ProgramInfo TEST_RDS_INFO = AidlTestUtils.makeProgramInfo( - AidlTestUtils.makeProgramSelector(ProgramSelector.PROGRAM_TYPE_FM, TEST_RDS_PI_ID), - TEST_RDS_PI_ID, new ProgramSelector.Identifier( - ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, /* value= */ 89_500), - SIGNAL_QUALITY); + + private static final ProgramSelector.Identifier TEST_DAB_FREQUENCY_ID = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, + /* value= */ 220_352); + private static final ProgramSelector.Identifier TEST_DAB_FREQUENCY_ID_ALT = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, + /* value= */ 220_064); + private static final ProgramSelector.Identifier TEST_DAB_SID_EXT_ID = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT, + /* value= */ 0xA000000111L); + private static final ProgramSelector.Identifier TEST_DAB_ENSEMBLE_ID = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE, + /* value= */ 0x1001); + private static final ProgramSelector TEST_DAB_SELECTOR = new ProgramSelector( + ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_SID_EXT_ID, + new ProgramSelector.Identifier[]{TEST_DAB_FREQUENCY_ID, TEST_DAB_ENSEMBLE_ID}, + /* vendorIds= */ null); + private static final ProgramSelector TEST_DAB_SELECTOR_ALT = new ProgramSelector( + ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_SID_EXT_ID, + new ProgramSelector.Identifier[]{TEST_DAB_FREQUENCY_ID_ALT, TEST_DAB_ENSEMBLE_ID}, + /* vendorIds= */ null); + private static final UniqueProgramIdentifier TEST_DAB_UNIQUE_ID = new UniqueProgramIdentifier( + TEST_DAB_SELECTOR); + private static final UniqueProgramIdentifier TEST_DAB_UNIQUE_ID_ALT = + new UniqueProgramIdentifier(TEST_DAB_SELECTOR_ALT); + private static final RadioManager.ProgramInfo TEST_DAB_INFO = + AidlTestUtils.makeProgramInfo(TEST_DAB_SELECTOR, TEST_DAB_SID_EXT_ID, + TEST_DAB_FREQUENCY_ID, SIGNAL_QUALITY); + private static final RadioManager.ProgramInfo TEST_DAB_INFO_ALT = + AidlTestUtils.makeProgramInfo(TEST_DAB_SELECTOR_ALT, TEST_DAB_SID_EXT_ID, + TEST_DAB_FREQUENCY_ID_ALT, SIGNAL_QUALITY); // Mocks @Mock @@ -129,6 +155,9 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { private TunerSession[] mTunerSessions; + @Rule + public final Expect expect = Expect.create(); + @Override protected void initializeSession(StaticMockitoSessionBuilder builder) { builder.spyStatic(RadioServiceUserController.class).spyStatic(CompatChanges.class) @@ -225,7 +254,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { openAidlClients(numSessions); for (int index = 0; index < numSessions; index++) { - assertWithMessage("Session of index %s close state", index) + expect.withMessage("Session of index %s close state", index) .that(mTunerSessions[index].isClosed()).isFalse(); } } @@ -257,7 +286,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { RadioManager.BandConfig config = mTunerSessions[0].getConfiguration(); - assertWithMessage("Session configuration").that(config) + expect.withMessage("Session configuration").that(config) .isEqualTo(FM_BAND_CONFIG); } @@ -267,7 +296,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].setMuted(/* mute= */ false); - assertWithMessage("Session mute state after setting unmuted") + expect.withMessage("Session mute state after setting unmuted") .that(mTunerSessions[0].isMuted()).isFalse(); } @@ -277,7 +306,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].setMuted(/* mute= */ true); - assertWithMessage("Session mute state after setting muted") + expect.withMessage("Session mute state after setting muted") .that(mTunerSessions[0].isMuted()).isTrue(); } @@ -287,7 +316,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].close(); - assertWithMessage("Close state of broadcast radio service session") + expect.withMessage("Close state of broadcast radio service session") .that(mTunerSessions[0].isClosed()).isTrue(); } @@ -301,11 +330,11 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { for (int index = 0; index < numSessions; index++) { if (index == closeIdx) { - assertWithMessage( + expect.withMessage( "Close state of broadcast radio service session of index %s", index) .that(mTunerSessions[index].isClosed()).isTrue(); } else { - assertWithMessage( + expect.withMessage( "Close state of broadcast radio service session of index %s", index) .that(mTunerSessions[index].isClosed()).isFalse(); } @@ -320,7 +349,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].close(errorCode); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onError(errorCode); - assertWithMessage("Close state of broadcast radio service session") + expect.withMessage("Close state of broadcast radio service session") .that(mTunerSessions[0].isClosed()).isTrue(); } @@ -334,7 +363,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { for (int index = 0; index < numSessions; index++) { verify(mAidlTunerCallbackMocks[index], CALLBACK_TIMEOUT).onError(errorCode); - assertWithMessage("Close state of broadcast radio service session of index %s", index) + expect.withMessage("Close state of broadcast radio service session of index %s", index) .that(mTunerSessions[index].isClosed()).isTrue(); } } @@ -383,22 +412,12 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { @Test public void tune_withUnsupportedSelector_throwsException() throws Exception { - ProgramSelector.Identifier dabPrimaryId = - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT, - /* value= */ 0xA000000111L); - ProgramSelector.Identifier[] dabSecondaryIds = new ProgramSelector.Identifier[]{ - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE, - /* value= */ 1337), - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, - /* value= */ 225648)}; - ProgramSelector unsupportedSelector = new ProgramSelector(ProgramSelector.PROGRAM_TYPE_DAB, - dabPrimaryId, dabSecondaryIds, /* vendorIds= */ null); openAidlClients(/* numClients= */ 1); UnsupportedOperationException thrown = assertThrows(UnsupportedOperationException.class, - () -> mTunerSessions[0].tune(unsupportedSelector)); + () -> mTunerSessions[0].tune(TEST_DAB_SELECTOR)); - assertWithMessage("Exception for tuning on unsupported program selector") + expect.withMessage("Exception for tuning on unsupported program selector") .that(thrown).hasMessageThat().contains("tune: NOT_SUPPORTED"); } @@ -413,7 +432,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> mTunerSessions[0].tune(invalidSel)); - assertWithMessage("Exception for tuning on DAB selector without DAB_SID_EXT primary id") + expect.withMessage("Exception for tuning on DAB selector without DAB_SID_EXT primary id") .that(thrown).hasMessageThat().contains("tune: INVALID_ARGUMENTS"); } @@ -457,7 +476,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].tune(sel); }); - assertWithMessage("Unknown error HAL exception when tuning") + expect.withMessage("Unknown error HAL exception when tuning") .that(thrown).hasMessageThat().contains("UNKNOWN_ERROR"); } @@ -520,7 +539,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].step(/* directionDown= */ true, /* skipSubChannel= */ false); }); - assertWithMessage("Exception for stepping when HAL is in invalid state") + expect.withMessage("Exception for stepping when HAL is in invalid state") .that(thrown).hasMessageThat().contains("INVALID_STATE"); } @@ -599,7 +618,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].seek(/* directionDown= */ true, /* skipSubChannel= */ false); }); - assertWithMessage("Internal error HAL exception when seeking") + expect.withMessage("Internal error HAL exception when seeking") .that(thrown).hasMessageThat().contains("INTERNAL_ERROR"); } @@ -636,7 +655,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].cancel(); }); - assertWithMessage("Exception for canceling when HAL throws remote exception") + expect.withMessage("Exception for canceling when HAL throws remote exception") .that(thrown).hasMessageThat().contains(exceptionMessage); } @@ -649,7 +668,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].getImage(imageId); }); - assertWithMessage("Get image exception") + expect.withMessage("Get image exception") .that(thrown).hasMessageThat().contains("Image ID is missing"); } @@ -660,7 +679,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { Bitmap imageTest = mTunerSessions[0].getImage(imageId); - assertWithMessage("Null image").that(imageTest).isEqualTo(null); + expect.withMessage("Null image").that(imageTest).isEqualTo(null); } @Test @@ -674,7 +693,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].getImage(/* id= */ 1); }); - assertWithMessage("Exception for getting image when HAL throws remote exception") + expect.withMessage("Exception for getting image when HAL throws remote exception") .that(thrown).hasMessageThat().contains(exceptionMessage); } @@ -702,18 +721,19 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { openAidlClients(/* numClients= */ 1); ProgramList.Filter filter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(), /* includeCategories= */ true, /* excludeModifications= */ false); - ProgramFilter halFilter = ConversionUtils.filterToHalProgramFilter(filter); - List<RadioManager.ProgramInfo> modified = List.of(TEST_FM_INFO, TEST_RDS_INFO); - List<ProgramSelector.Identifier> removed = new ArrayList<>(); + List<RadioManager.ProgramInfo> modified = List.of(TEST_FM_INFO, TEST_DAB_INFO, + TEST_DAB_INFO_ALT); + List<ProgramSelector.Identifier> halRemoved = new ArrayList<>(); + List<UniqueProgramIdentifier> removed = new ArrayList<>(); ProgramListChunk halProgramList = AidlTestUtils.makeHalChunk(/* purge= */ true, - /* complete= */ true, modified, removed); + /* complete= */ true, modified, halRemoved); ProgramList.Chunk expectedProgramList = AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true, modified, removed); mTunerSessions[0].startProgramListUpdates(filter); mHalTunerCallback.onProgramListUpdated(halProgramList); - verify(mBroadcastRadioMock).startProgramListUpdates(halFilter); + verifyHalProgramListUpdatesInvocation(filter); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT) .onProgramListUpdated(expectedProgramList); } @@ -723,19 +743,23 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { openAidlClients(/* numClients= */ 1); ProgramList.Filter filter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(), /* includeCategories= */ true, /* excludeModifications= */ false); + List<RadioManager.ProgramInfo> modifiedInfo = List.of(TEST_FM_INFO, TEST_DAB_INFO, + TEST_DAB_INFO_ALT); mTunerSessions[0].startProgramListUpdates(filter); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ true, - /* complete= */ true, List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>())); + /* complete= */ true, modifiedInfo, new ArrayList<>())); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated( - AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true, - List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>())); + AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true, modifiedInfo, + new ArrayList<>())); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false, - /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID))); + /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), + List.of(TEST_DAB_SID_EXT_ID))); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated( AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true, - List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID))); + List.of(TEST_FM_INFO_MODIFIED), + List.of(TEST_DAB_UNIQUE_ID, TEST_DAB_UNIQUE_ID_ALT))); } @Test @@ -743,17 +767,21 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { openAidlClients(/* numClients= */ 1); ProgramList.Filter filter = new ProgramList.Filter(new ArraySet<>(), new ArraySet<>(), /* includeCategories= */ true, /* excludeModifications= */ false); + List<RadioManager.ProgramInfo> modifiedInfo = List.of(TEST_FM_INFO, TEST_DAB_INFO, + TEST_DAB_INFO_ALT); mTunerSessions[0].startProgramListUpdates(filter); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ true, - /* complete= */ true, List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>())); + /* complete= */ true, modifiedInfo, new ArrayList<>())); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated( - AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true, - List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>())); + AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true, modifiedInfo, + new ArrayList<>())); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false, - /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID))); + /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), + List.of(TEST_DAB_SID_EXT_ID))); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated( AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true, - List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID))); + List.of(TEST_FM_INFO_MODIFIED), + List.of(TEST_DAB_UNIQUE_ID, TEST_DAB_UNIQUE_ID_ALT))); mTunerSessions[0].startProgramListUpdates(filter); @@ -766,40 +794,44 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { @Test public void startProgramListUpdates_withNullFilter() throws Exception { openAidlClients(/* numClients= */ 1); + List<RadioManager.ProgramInfo> modifiedInfo = List.of(TEST_FM_INFO, TEST_DAB_INFO, + TEST_DAB_INFO_ALT); mTunerSessions[0].startProgramListUpdates(/* filter= */ null); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ true, - /* complete= */ true, List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>())); + /* complete= */ true, modifiedInfo, new ArrayList<>())); verify(mBroadcastRadioMock).startProgramListUpdates(any()); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated( - AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true, - List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>())); + AidlTestUtils.makeChunk(/* purge= */ true, /* complete= */ true, modifiedInfo, + new ArrayList<>())); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false, - /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID))); + /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), + List.of(TEST_DAB_SID_EXT_ID))); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated( AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true, - List.of(TEST_FM_INFO_MODIFIED), List.of(TEST_RDS_PI_ID))); + List.of(TEST_FM_INFO_MODIFIED), + List.of(TEST_DAB_UNIQUE_ID, TEST_DAB_UNIQUE_ID_ALT))); } @Test public void startProgramListUpdates_withIdFilter() throws Exception { openAidlClients(/* numClients= */ 1); ProgramList.Filter idFilter = new ProgramList.Filter(new ArraySet<>(), - Set.of(TEST_RDS_PI_ID), /* includeCategories= */ true, + Set.of(TEST_DAB_SID_EXT_ID), /* includeCategories= */ true, /* excludeModifications= */ true); - ProgramFilter halFilter = ConversionUtils.filterToHalProgramFilter(idFilter); mTunerSessions[0].startProgramListUpdates(idFilter); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false, - /* complete= */ true, List.of(TEST_RDS_INFO), new ArrayList<>())); + /* complete= */ true, List.of(TEST_DAB_INFO, TEST_DAB_INFO_ALT), + new ArrayList<>())); - verify(mBroadcastRadioMock).startProgramListUpdates(halFilter); + verifyHalProgramListUpdatesInvocation(idFilter); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated( AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true, - List.of(TEST_RDS_INFO), new ArrayList<>())); + List.of(TEST_DAB_INFO, TEST_DAB_INFO_ALT), new ArrayList<>())); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false, /* complete= */ true, List.of(TEST_FM_INFO), new ArrayList<>())); @@ -811,50 +843,52 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { public void startProgramListUpdates_withFilterExcludingModifications() throws Exception { openAidlClients(/* numClients= */ 1); ProgramList.Filter filterExcludingModifications = new ProgramList.Filter( - Set.of(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY), new ArraySet<>(), + Set.of(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT, + ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY), new ArraySet<>(), /* includeCategories= */ true, /* excludeModifications= */ true); - ProgramFilter halFilter = - ConversionUtils.filterToHalProgramFilter(filterExcludingModifications); mTunerSessions[0].startProgramListUpdates(filterExcludingModifications); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false, - /* complete= */ true, List.of(TEST_FM_INFO), new ArrayList<>())); + /* complete= */ true, List.of(TEST_FM_INFO, TEST_DAB_INFO), new ArrayList<>())); - verify(mBroadcastRadioMock).startProgramListUpdates(halFilter); + verifyHalProgramListUpdatesInvocation(filterExcludingModifications); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated( AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true, - List.of(TEST_FM_INFO), new ArrayList<>())); + List.of(TEST_FM_INFO, TEST_DAB_INFO), new ArrayList<>())); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false, - /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), new ArrayList<>())); + /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED, TEST_DAB_INFO_ALT), + new ArrayList<>())); - verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated(any()); + verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated( + AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true, + List.of(TEST_DAB_INFO_ALT), new ArrayList<>())); } @Test public void startProgramListUpdates_withFilterIncludingModifications() throws Exception { openAidlClients(/* numClients= */ 1); ProgramList.Filter filterIncludingModifications = new ProgramList.Filter( - Set.of(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY), new ArraySet<>(), + Set.of(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT, + ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY), new ArraySet<>(), /* includeCategories= */ true, /* excludeModifications= */ false); - ProgramFilter halFilter = - ConversionUtils.filterToHalProgramFilter(filterIncludingModifications); mTunerSessions[0].startProgramListUpdates(filterIncludingModifications); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false, - /* complete= */ true, List.of(TEST_FM_INFO), new ArrayList<>())); + /* complete= */ true, List.of(TEST_FM_INFO, TEST_DAB_INFO), new ArrayList<>())); - verify(mBroadcastRadioMock).startProgramListUpdates(halFilter); + verifyHalProgramListUpdatesInvocation(filterIncludingModifications); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated( AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true, - List.of(TEST_FM_INFO), new ArrayList<>())); + List.of(TEST_FM_INFO, TEST_DAB_INFO), new ArrayList<>())); mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false, - /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED), new ArrayList<>())); + /* complete= */ true, List.of(TEST_FM_INFO_MODIFIED, TEST_DAB_INFO_ALT), + new ArrayList<>())); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT).onProgramListUpdated( AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true, - List.of(TEST_FM_INFO_MODIFIED), new ArrayList<>())); + List.of(TEST_FM_INFO_MODIFIED, TEST_DAB_INFO_ALT), new ArrayList<>())); } @Test @@ -910,7 +944,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { int numSessions = 3; openAidlClients(numSessions); List<ProgramList.Filter> filters = List.of(new ProgramList.Filter( - Set.of(ProgramSelector.IDENTIFIER_TYPE_RDS_PI), new ArraySet<>(), + Set.of(ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT), new ArraySet<>(), /* includeCategories= */ true, /* excludeModifications= */ false), new ProgramList.Filter(new ArraySet<>(), Set.of(TEST_FM_FREQUENCY_ID), /* includeCategories= */ false, /* excludeModifications= */ true), @@ -922,18 +956,20 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { } mHalTunerCallback.onProgramListUpdated(AidlTestUtils.makeHalChunk(/* purge= */ false, - /* complete= */ true, List.of(TEST_FM_INFO, TEST_RDS_INFO), new ArrayList<>())); + /* complete= */ true, List.of(TEST_FM_INFO, TEST_DAB_INFO, TEST_DAB_INFO_ALT), + new ArrayList<>())); verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT) .onProgramListUpdated(AidlTestUtils.makeChunk(/* purge= */ false, - /* complete= */ true, List.of(TEST_RDS_INFO), new ArrayList<>())); + /* complete= */ true, List.of(TEST_DAB_INFO, TEST_DAB_INFO_ALT), + new ArrayList<>())); verify(mAidlTunerCallbackMocks[1], CALLBACK_TIMEOUT) .onProgramListUpdated(AidlTestUtils.makeChunk(/* purge= */ false, /* complete= */ true, List.of(TEST_FM_INFO), new ArrayList<>())); verify(mAidlTunerCallbackMocks[2], CALLBACK_TIMEOUT) .onProgramListUpdated(AidlTestUtils.makeChunk(/* purge= */ false, - /* complete= */ true, List.of(TEST_RDS_INFO, TEST_FM_INFO), - new ArrayList<>())); + /* complete= */ true, List.of(TEST_DAB_INFO, TEST_DAB_INFO_ALT, + TEST_FM_INFO), new ArrayList<>())); } @Test @@ -958,7 +994,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].startProgramListUpdates(/* filter= */ null); }); - assertWithMessage("Unknown error HAL exception when updating program list") + expect.withMessage("Unknown error HAL exception when updating program list") .that(thrown).hasMessageThat().contains("UNKNOWN_ERROR"); } @@ -995,7 +1031,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { boolean isSupported = mTunerSessions[0].isConfigFlagSupported(flag); verify(mBroadcastRadioMock).isConfigFlagSet(flag); - assertWithMessage("Config flag %s is supported", flag).that(isSupported).isFalse(); + expect.withMessage("Config flag %s is supported", flag).that(isSupported).isFalse(); } @Test @@ -1006,7 +1042,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { boolean isSupported = mTunerSessions[0].isConfigFlagSupported(flag); verify(mBroadcastRadioMock).isConfigFlagSet(flag); - assertWithMessage("Config flag %s is supported", flag).that(isSupported).isTrue(); + expect.withMessage("Config flag %s is supported", flag).that(isSupported).isTrue(); } @Test @@ -1018,7 +1054,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].setConfigFlag(flag, /* value= */ true); }); - assertWithMessage("Exception for setting unsupported flag %s", flag) + expect.withMessage("Exception for setting unsupported flag %s", flag) .that(thrown).hasMessageThat().contains("setConfigFlag: NOT_SUPPORTED"); } @@ -1063,7 +1099,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].isConfigFlagSet(flag); }); - assertWithMessage("Exception for checking if unsupported flag %s is set", flag) + expect.withMessage("Exception for checking if unsupported flag %s is set", flag) .that(thrown).hasMessageThat().contains("isConfigFlagSet: NOT_SUPPORTED"); } @@ -1076,7 +1112,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { boolean isSet = mTunerSessions[0].isConfigFlagSet(flag); - assertWithMessage("Config flag %s is set", flag) + expect.withMessage("Config flag %s is set", flag) .that(isSet).isEqualTo(expectedConfigFlagValue); } @@ -1090,7 +1126,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].isConfigFlagSet(flag); }); - assertWithMessage("Exception for checking config flag when HAL throws remote exception") + expect.withMessage("Exception for checking config flag when HAL throws remote exception") .that(thrown).hasMessageThat().contains("Failed to check flag"); } @@ -1131,7 +1167,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].setParameters(parametersSet); }); - assertWithMessage("Exception for setting parameters when HAL throws remote exception") + expect.withMessage("Exception for setting parameters when HAL throws remote exception") .that(thrown).hasMessageThat().contains(exceptionMessage); } @@ -1157,7 +1193,7 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { mTunerSessions[0].getParameters(parameterKeys); }); - assertWithMessage("Exception for getting parameters when HAL throws remote exception") + expect.withMessage("Exception for getting parameters when HAL throws remote exception") .that(thrown).hasMessageThat().contains(exceptionMessage); } @@ -1264,4 +1300,24 @@ public final class TunerSessionTest extends ExtendedRadioMockitoTestCase { } return seekFrequency; } + + private void verifyHalProgramListUpdatesInvocation(ProgramList.Filter filter) throws Exception { + ProgramFilter halFilterExpected = ConversionUtils.filterToHalProgramFilter(filter); + ArgumentCaptor<ProgramFilter> halFilterCaptor = ArgumentCaptor.forClass( + ProgramFilter.class); + verify(mBroadcastRadioMock).startProgramListUpdates(halFilterCaptor.capture()); + ProgramFilter halFilterInvoked = halFilterCaptor.getValue(); + expect.withMessage("Filtered identifier types").that( + halFilterInvoked.identifierTypes).asList().containsExactlyElementsIn(Arrays.stream( + halFilterExpected.identifierTypes).boxed().toArray(Integer[]::new)); + expect.withMessage("Filtered identifiers").that( + halFilterInvoked.identifiers).asList() + .containsExactlyElementsIn(halFilterExpected.identifiers); + expect.withMessage("Categories-included filter") + .that(halFilterInvoked.includeCategories) + .isEqualTo(halFilterExpected.includeCategories); + expect.withMessage("Modifications-excluded filter") + .that(halFilterInvoked.excludeModifications) + .isEqualTo(halFilterExpected.excludeModifications); + } } diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java index ec55ddbe1a4a..fbb446b5bc23 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/ProgramInfoCacheTest.java @@ -21,12 +21,16 @@ import android.hardware.broadcastradio.V2_0.ProgramListChunk; import android.hardware.radio.ProgramList; import android.hardware.radio.ProgramSelector; import android.hardware.radio.RadioManager; +import android.hardware.radio.UniqueProgramIdentifier; import android.test.suitebuilder.annotation.MediumTest; import androidx.test.runner.AndroidJUnit4; import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase; +import com.google.common.truth.Expect; + +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -40,188 +44,221 @@ import java.util.Set; @RunWith(AndroidJUnit4.class) @MediumTest public class ProgramInfoCacheTest extends ExtendedRadioMockitoTestCase { - private static final String TAG = "BroadcastRadioTests.ProgramInfoCache"; + private static final int TEST_QUALITY = 1; + + private static final ProgramSelector.Identifier TEST_AM_FM_ID = new ProgramSelector.Identifier( + ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, /* value= */ 88500); + private static final ProgramSelector TEST_AM_FM_SELECTOR = TestUtils.makeProgramSelector( + ProgramSelector.PROGRAM_TYPE_FM, TEST_AM_FM_ID); + private static final RadioManager.ProgramInfo TEST_AM_FM_INFO = TestUtils.makeProgramInfo( + TEST_AM_FM_SELECTOR, TEST_QUALITY); - private final ProgramSelector.Identifier mAmFmIdentifier = - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, 88500); - private final RadioManager.ProgramInfo mAmFmInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_FM, mAmFmIdentifier, 0); + private static final ProgramSelector.Identifier TEST_RDS_ID = new ProgramSelector.Identifier( + ProgramSelector.IDENTIFIER_TYPE_RDS_PI, /* value= */ 15019); + private static final ProgramSelector TEST_RDS_SELECTOR = TestUtils.makeProgramSelector( + ProgramSelector.PROGRAM_TYPE_FM, TEST_RDS_ID); + private static final RadioManager.ProgramInfo TEST_RDS_INFO = TestUtils.makeProgramInfo( + TEST_RDS_SELECTOR, TEST_QUALITY); - private final ProgramSelector.Identifier mRdsIdentifier = - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_RDS_PI, 15019); - private final RadioManager.ProgramInfo mRdsInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_FM, mRdsIdentifier, 0); + private static final ProgramSelector TEST_HD_SELECTOR = TestUtils.makeProgramSelector( + ProgramSelector.PROGRAM_TYPE_FM_HD, new ProgramSelector.Identifier( + ProgramSelector.IDENTIFIER_TYPE_HD_STATION_ID_EXT, + /* value= */ 0x17C14100000001L)); - private final ProgramSelector.Identifier mDabEnsembleIdentifier = - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE, 1337); - private final RadioManager.ProgramInfo mDabEnsembleInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_DAB, mDabEnsembleIdentifier, 0); + private static final ProgramSelector.Identifier TEST_DAB_SID_ID = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT, + /* value= */ 0xA000000111L); + private static final ProgramSelector.Identifier TEST_DAB_ENSEMBLE_ID = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE, + /* value= */ 0x1001); + private static final ProgramSelector.Identifier TEST_DAB_FREQUENCY_ID = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, + /* value= */ 220_352); + private static final ProgramSelector TEST_DAB_SELECTOR = TestUtils.makeProgramSelector( + ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_SID_ID, + new ProgramSelector.Identifier[]{TEST_DAB_FREQUENCY_ID, TEST_DAB_ENSEMBLE_ID}); + private static final UniqueProgramIdentifier TEST_DAB_UNIQUE_ID = + new UniqueProgramIdentifier(TEST_DAB_SELECTOR); + private static final RadioManager.ProgramInfo TEST_DAB_INFO = TestUtils.makeProgramInfo( + TEST_DAB_SELECTOR, TEST_QUALITY); + private static final ProgramSelector.Identifier TEST_VENDOR_ID = new ProgramSelector.Identifier( + ProgramSelector.IDENTIFIER_TYPE_VENDOR_START, /* value= */ 9001); + private static final ProgramSelector TEST_VENDOR_SELECTOR = TestUtils.makeProgramSelector( + ProgramSelector.PROGRAM_TYPE_VENDOR_START, TEST_VENDOR_ID); + private static final UniqueProgramIdentifier TEST_VENDOR_UNIQUE_ID = + new UniqueProgramIdentifier(TEST_VENDOR_SELECTOR); + private static final RadioManager.ProgramInfo TEST_VENDOR_INFO = TestUtils.makeProgramInfo( + TEST_VENDOR_SELECTOR, TEST_QUALITY); - private final ProgramSelector.Identifier mVendorCustomIdentifier = - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_VENDOR_START, 9001); - private final RadioManager.ProgramInfo mVendorCustomInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_VENDOR_START, mVendorCustomIdentifier, 0); + private static final ProgramInfoCache FULL_PROGRAM_INFO_CACHE = new ProgramInfoCache( + /* filter= */ null, /* complete= */ true, TEST_AM_FM_INFO, TEST_RDS_INFO, TEST_DAB_INFO, + TEST_VENDOR_INFO); - // HAL-side ProgramInfoCache containing all of the above ProgramInfos. - private final ProgramInfoCache mAllProgramInfos = new ProgramInfoCache(null, true, mAmFmInfo, - mRdsInfo, mDabEnsembleInfo, mVendorCustomInfo); + @Rule + public final Expect expect = Expect.create(); @Test public void testUpdateFromHal() { // First test updating an incomplete cache with a purging, complete chunk. - ProgramInfoCache cache = new ProgramInfoCache(null, false, mAmFmInfo); + ProgramInfoCache cache = new ProgramInfoCache(null, false, TEST_AM_FM_INFO); ProgramListChunk chunk = new ProgramListChunk(); chunk.purge = true; chunk.complete = true; - chunk.modified.add(TestUtils.programInfoToHal(mRdsInfo)); - chunk.modified.add(TestUtils.programInfoToHal(mDabEnsembleInfo)); + chunk.modified.add(TestUtils.programInfoToHal(TEST_RDS_INFO)); + chunk.modified.add(TestUtils.programInfoToHal(TEST_DAB_INFO)); cache.updateFromHalProgramListChunk(chunk); - assertTrue(cache.programInfosAreExactly(mRdsInfo, mDabEnsembleInfo)); + expect.withMessage("Program info cache updated with a purging complete chunk") + .that(cache.toProgramInfoList()).containsExactly(TEST_RDS_INFO, TEST_DAB_INFO); assertTrue(cache.isComplete()); // Then test a non-purging, incomplete chunk. chunk.purge = false; chunk.complete = false; chunk.modified.clear(); - RadioManager.ProgramInfo updatedRdsInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_FM, mRdsIdentifier, 1); + RadioManager.ProgramInfo updatedRdsInfo = TestUtils.makeProgramInfo(TEST_RDS_SELECTOR, 1); chunk.modified.add(TestUtils.programInfoToHal(updatedRdsInfo)); - chunk.modified.add(TestUtils.programInfoToHal(mVendorCustomInfo)); - chunk.removed.add(Convert.programIdentifierToHal(mDabEnsembleIdentifier)); + chunk.modified.add(TestUtils.programInfoToHal(TEST_VENDOR_INFO)); + chunk.removed.add(Convert.programIdentifierToHal(TEST_DAB_SID_ID)); cache.updateFromHalProgramListChunk(chunk); - assertTrue(cache.programInfosAreExactly(updatedRdsInfo, mVendorCustomInfo)); + expect.withMessage("Program info cache updated with non-puring incomplete chunk") + .that(cache.toProgramInfoList()).containsExactly(updatedRdsInfo, TEST_VENDOR_INFO); assertFalse(cache.isComplete()); } @Test public void testNullFilter() { ProgramInfoCache cache = new ProgramInfoCache(null, true); - cache.filterAndUpdateFrom(mAllProgramInfos, false); - assertTrue(cache.programInfosAreExactly(mAmFmInfo, mRdsInfo, mDabEnsembleInfo, - mVendorCustomInfo)); + cache.filterAndUpdateFrom(FULL_PROGRAM_INFO_CACHE, false); + expect.withMessage("Program info cache with null filter") + .that(cache.toProgramInfoList()).containsExactly(TEST_AM_FM_INFO, TEST_RDS_INFO, + TEST_DAB_INFO, TEST_VENDOR_INFO); } @Test public void testEmptyFilter() { ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(new HashSet<Integer>(), new HashSet<ProgramSelector.Identifier>(), true, false)); - cache.filterAndUpdateFrom(mAllProgramInfos, false); - assertTrue(cache.programInfosAreExactly(mAmFmInfo, mRdsInfo, mDabEnsembleInfo, - mVendorCustomInfo)); + cache.filterAndUpdateFrom(FULL_PROGRAM_INFO_CACHE, false); + expect.withMessage("Program info cache with empty filter") + .that(cache.toProgramInfoList()).containsExactly(TEST_AM_FM_INFO, TEST_RDS_INFO, + TEST_DAB_INFO, TEST_VENDOR_INFO); } @Test public void testFilterByType() { HashSet<Integer> filterTypes = new HashSet<>(); filterTypes.add(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY); - filterTypes.add(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE); + filterTypes.add(ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT); ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(filterTypes, new HashSet<ProgramSelector.Identifier>(), true, false)); - cache.filterAndUpdateFrom(mAllProgramInfos, false); - assertTrue(cache.programInfosAreExactly(mAmFmInfo, mDabEnsembleInfo)); + cache.filterAndUpdateFrom(FULL_PROGRAM_INFO_CACHE, false); + expect.withMessage("Program info cache with type filter") + .that(cache.toProgramInfoList()).containsExactly(TEST_AM_FM_INFO, TEST_DAB_INFO); } @Test public void testFilterByIdentifier() { HashSet<ProgramSelector.Identifier> filterIds = new HashSet<>(); - filterIds.add(mRdsIdentifier); - filterIds.add(mVendorCustomIdentifier); + filterIds.add(TEST_RDS_ID); + filterIds.add(TEST_VENDOR_ID); ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(new HashSet<Integer>(), filterIds, true, false)); - cache.filterAndUpdateFrom(mAllProgramInfos, false); - assertTrue(cache.programInfosAreExactly(mRdsInfo, mVendorCustomInfo)); + cache.filterAndUpdateFrom(FULL_PROGRAM_INFO_CACHE, false); + expect.withMessage("Program info cache with identifier filter") + .that(cache.toProgramInfoList()).containsExactly(TEST_RDS_INFO, TEST_VENDOR_INFO); } @Test public void testFilterExcludeCategories() { ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(new HashSet<Integer>(), new HashSet<ProgramSelector.Identifier>(), false, false)); - cache.filterAndUpdateFrom(mAllProgramInfos, false); - assertTrue(cache.programInfosAreExactly(mAmFmInfo, mRdsInfo)); + cache.filterAndUpdateFrom(FULL_PROGRAM_INFO_CACHE, false); + expect.withMessage("Program info cache with filter excluding categories") + .that(cache.toProgramInfoList()).containsExactly(TEST_AM_FM_INFO, TEST_RDS_INFO, + TEST_DAB_INFO); } @Test public void testPurgeUpdateChunks() { - ProgramInfoCache cache = new ProgramInfoCache(null, false, mAmFmInfo); + ProgramInfoCache cache = new ProgramInfoCache(null, false, TEST_AM_FM_INFO); List<ProgramList.Chunk> chunks = - cache.filterAndUpdateFromInternal(mAllProgramInfos, true, 3, 3); + cache.filterAndUpdateFromInternal(FULL_PROGRAM_INFO_CACHE, true, 3, 3); assertEquals(2, chunks.size()); verifyChunkListFlags(chunks, true, true); - verifyChunkListModified(chunks, 3, mAmFmInfo, mRdsInfo, mDabEnsembleInfo, - mVendorCustomInfo); + verifyChunkListModified(chunks, 3, TEST_AM_FM_INFO, TEST_RDS_INFO, TEST_DAB_INFO, + TEST_VENDOR_INFO); verifyChunkListRemoved(chunks, 0); } @Test public void testDeltaUpdateChunksModificationsIncluded() { // Create a cache with a filter that allows modifications, and set its contents to - // mAmFmInfo, mRdsInfo, mDabEnsembleInfo, and mVendorCustomInfo. - ProgramInfoCache cache = new ProgramInfoCache(null, true, mAmFmInfo, mRdsInfo, - mDabEnsembleInfo, mVendorCustomInfo); + // TEST_AM_FM_INFO, TEST_RDS_INFO, TEST_DAB_INFO, and TEST_VENDOR_INFO. + ProgramInfoCache cache = new ProgramInfoCache(null, true, TEST_AM_FM_INFO, TEST_RDS_INFO, + TEST_DAB_INFO, TEST_VENDOR_INFO); // Create a HAL cache that: // - Is complete. - // - Retains mAmFmInfo. - // - Replaces mRdsInfo with updatedRdsInfo. - // - Drops mDabEnsembleInfo and mVendorCustomInfo. - // - Introduces a new SXM info. - RadioManager.ProgramInfo updatedRdsInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_FM, mRdsIdentifier, 1); - RadioManager.ProgramInfo newSxmInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_SXM, - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_SXM_CHANNEL, 12345), - 0); - ProgramInfoCache halCache = new ProgramInfoCache(null, true, mAmFmInfo, updatedRdsInfo, - newSxmInfo); + // - Retains TEST_AM_FM_INFO. + // - Replaces TEST_RDS_INFO with updatedRdsInfo. + // - Drops TEST_DAB_INFO and TEST_VENDOR_INFO. + // - Introduces a new HD info. + RadioManager.ProgramInfo updatedRdsInfo = TestUtils.makeProgramInfo(TEST_RDS_SELECTOR, + TEST_QUALITY + 1); + RadioManager.ProgramInfo newHdInfo = TestUtils.makeProgramInfo(TEST_HD_SELECTOR, + TEST_QUALITY); + ProgramInfoCache halCache = new ProgramInfoCache(null, true, TEST_AM_FM_INFO, + updatedRdsInfo, newHdInfo); // Update the cache and verify: // - The final chunk's complete flag is set. - // - mAmFmInfo is retained and not reported in the chunks. - // - updatedRdsInfo should appear as an update to mRdsInfo. - // - newSxmInfo should appear as a new entry. - // - mDabEnsembleInfo and mVendorCustomInfo should be reported as removed. + // - TEST_AM_FM_INFO is retained and not reported in the chunks. + // - updatedRdsInfo should appear as an update to TEST_RDS_INFO. + // - newHdInfo should appear as a new entry. + // - TEST_DAB_INFO and TEST_VENDOR_INFO should be reported as removed. List<ProgramList.Chunk> chunks = cache.filterAndUpdateFromInternal(halCache, false, 5, 1); - assertTrue(cache.programInfosAreExactly(mAmFmInfo, updatedRdsInfo, newSxmInfo)); + expect.withMessage("Program info cache with modification included") + .that(cache.toProgramInfoList()).containsExactly(TEST_AM_FM_INFO, updatedRdsInfo, + newHdInfo); assertEquals(2, chunks.size()); verifyChunkListFlags(chunks, false, true); - verifyChunkListModified(chunks, 5, updatedRdsInfo, newSxmInfo); - verifyChunkListRemoved(chunks, 1, mDabEnsembleIdentifier, mVendorCustomIdentifier); + verifyChunkListModified(chunks, 5, updatedRdsInfo, newHdInfo); + verifyChunkListRemoved(chunks, 1, TEST_DAB_UNIQUE_ID, TEST_VENDOR_UNIQUE_ID); } @Test public void testDeltaUpdateChunksModificationsExcluded() { // Create a cache with a filter that excludes modifications, and set its contents to - // mAmFmInfo, mRdsInfo, mDabEnsembleInfo, and mVendorCustomInfo. + // TEST_AM_FM_INFO, TEST_RDS_INFO, TEST_DAB_INFO, and TEST_VENDOR_INFO. ProgramInfoCache cache = new ProgramInfoCache(new ProgramList.Filter(new HashSet<Integer>(), - new HashSet<ProgramSelector.Identifier>(), true, true), true, mAmFmInfo, mRdsInfo, - mDabEnsembleInfo, mVendorCustomInfo); + new HashSet<ProgramSelector.Identifier>(), true, true), true, + TEST_AM_FM_INFO, TEST_RDS_INFO, TEST_DAB_INFO, TEST_VENDOR_INFO); // Create a HAL cache that: // - Is incomplete. - // - Retains mAmFmInfo. - // - Replaces mRdsInfo with updatedRdsInfo. - // - Drops mDabEnsembleInfo and mVendorCustomInfo. - // - Introduces a new SXM info. - RadioManager.ProgramInfo updatedRdsInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_FM, mRdsIdentifier, 1); - RadioManager.ProgramInfo newSxmInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_SXM, - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_SXM_CHANNEL, 12345), - 0); - ProgramInfoCache halCache = new ProgramInfoCache(null, false, mAmFmInfo, updatedRdsInfo, - newSxmInfo); + // - Retains TEST_AM_FM_INFO. + // - Replaces TEST_RDS_INFO with updatedRdsInfo. + // - Drops TEST_DAB_INFO and TEST_VENDOR_INFO. + // - Introduces a new HD info. + RadioManager.ProgramInfo updatedRdsInfo = TestUtils.makeProgramInfo(TEST_RDS_SELECTOR, 1); + RadioManager.ProgramInfo newHdInfo = TestUtils.makeProgramInfo(TEST_HD_SELECTOR, + TEST_QUALITY); + ProgramInfoCache halCache = new ProgramInfoCache(null, false, TEST_AM_FM_INFO, + updatedRdsInfo, newHdInfo); // Update the cache and verify: // - All complete flags are false. - // - mAmFmInfo and mRdsInfo are retained and not reported in the chunks. - // - newSxmInfo should appear as a new entry. - // - mDabEnsembleInfo and mVendorCustomInfo should be reported as removed. + // - TEST_AM_FM_INFO and TEST_RDS_INFO are retained and not reported in the chunks. + // - newHdInfo should appear as a new entry. + // - TEST_DAB_INFO and TEST_VENDOR_INFO should be reported as removed. List<ProgramList.Chunk> chunks = cache.filterAndUpdateFromInternal(halCache, false, 5, 1); - assertTrue(cache.programInfosAreExactly(mAmFmInfo, mRdsInfo, newSxmInfo)); + expect.withMessage("Program info cache with modification excluded") + .that(cache.toProgramInfoList()).containsExactly(TEST_AM_FM_INFO, TEST_RDS_INFO, + newHdInfo); assertEquals(2, chunks.size()); verifyChunkListFlags(chunks, false, false); - verifyChunkListModified(chunks, 5, newSxmInfo); - verifyChunkListRemoved(chunks, 1, mDabEnsembleIdentifier, mVendorCustomIdentifier); + verifyChunkListModified(chunks, 5, newHdInfo); + verifyChunkListRemoved(chunks, 1, TEST_DAB_UNIQUE_ID, TEST_VENDOR_UNIQUE_ID); } // Verifies that: @@ -271,20 +308,21 @@ public class ProgramInfoCacheTest extends ExtendedRadioMockitoTestCase { // - Each chunk's removed array has a similar number of elements. // - Each element of expectedIdentifiers appears in a chunk. private static void verifyChunkListRemoved(List<ProgramList.Chunk> chunks, - int maxRemovedPerChunk, ProgramSelector.Identifier... expectedIdentifiers) { + int maxRemovedPerChunk, + UniqueProgramIdentifier... expectedIdentifiers) { if (chunks.isEmpty()) { assertEquals(0, expectedIdentifiers.length); return; } - HashSet<ProgramSelector.Identifier> expectedSet = new HashSet<>(); - for (ProgramSelector.Identifier identifier : expectedIdentifiers) { + HashSet<UniqueProgramIdentifier> expectedSet = new HashSet<>(); + for (UniqueProgramIdentifier identifier : expectedIdentifiers) { expectedSet.add(identifier); } - HashSet<ProgramSelector.Identifier> actualSet = new HashSet<>(); + HashSet<UniqueProgramIdentifier> actualSet = new HashSet<>(); int chunk0NumRemoved = chunks.get(0).getRemoved().size(); for (ProgramList.Chunk chunk : chunks) { - Set<ProgramSelector.Identifier> chunkRemoved = chunk.getRemoved(); + Set<UniqueProgramIdentifier> chunkRemoved = chunk.getRemoved(); assertTrue(chunkRemoved.size() <= maxRemovedPerChunk); assertTrue(Math.abs(chunkRemoved.size() - chunk0NumRemoved) <= 1); actualSet.addAll(chunkRemoved); diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java index 7d604d497984..8c16d79133ce 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/StartProgramListUpdatesFanoutTest.java @@ -35,6 +35,7 @@ import android.hardware.broadcastradio.V2_0.Result; import android.hardware.radio.ProgramList; import android.hardware.radio.ProgramSelector; import android.hardware.radio.RadioManager; +import android.hardware.radio.UniqueProgramIdentifier; import android.os.RemoteException; import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder; @@ -72,22 +73,42 @@ public class StartProgramListUpdatesFanoutTest extends ExtendedRadioMockitoTestC private TunerSession[] mTunerSessions; // Data objects used during tests - private final ProgramSelector.Identifier mAmFmIdentifier = - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, 88500); - private final RadioManager.ProgramInfo mAmFmInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_FM, mAmFmIdentifier, 0); - private final RadioManager.ProgramInfo mModifiedAmFmInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_FM, mAmFmIdentifier, 1); - - private final ProgramSelector.Identifier mRdsIdentifier = - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_RDS_PI, 15019); - private final RadioManager.ProgramInfo mRdsInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_FM, mRdsIdentifier, 0); - - private final ProgramSelector.Identifier mDabEnsembleIdentifier = - new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE, 1337); - private final RadioManager.ProgramInfo mDabEnsembleInfo = TestUtils.makeProgramInfo( - ProgramSelector.PROGRAM_TYPE_DAB, mDabEnsembleIdentifier, 0); + private static final int TEST_QUALITY = 0; + private static final ProgramSelector.Identifier TEST_AM_FM_ID = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY, + /* value= */ 88_500); + private static final ProgramSelector TEST_AM_FM_SELECTOR = TestUtils.makeProgramSelector( + ProgramSelector.PROGRAM_TYPE_FM, TEST_AM_FM_ID); + private static final RadioManager.ProgramInfo TEST_AM_FM_INFO = TestUtils.makeProgramInfo( + TEST_AM_FM_SELECTOR, TEST_QUALITY); + private static final RadioManager.ProgramInfo TEST_AM_FM_MODIFIED_INFO = + TestUtils.makeProgramInfo(TEST_AM_FM_SELECTOR, TEST_QUALITY + 1); + + private static final ProgramSelector.Identifier TEST_RDS_ID = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_RDS_PI, + /* value= */ 15_019); + private static final ProgramSelector TEST_RDS_SELECTOR = TestUtils.makeProgramSelector( + ProgramSelector.PROGRAM_TYPE_FM, TEST_RDS_ID); + + private static final UniqueProgramIdentifier TEST_RDS_UNIQUE_ID = new UniqueProgramIdentifier( + TEST_RDS_ID); + private static final RadioManager.ProgramInfo TEST_RDS_INFO = TestUtils.makeProgramInfo( + TEST_RDS_SELECTOR, TEST_QUALITY); + + private static final ProgramSelector.Identifier TEST_DAB_SID_ID = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT, + /* value= */ 0xA000000111L); + private static final ProgramSelector.Identifier TEST_DAB_ENSEMBLE_ID = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_ENSEMBLE, + /* value= */ 0x1001); + private static final ProgramSelector.Identifier TEST_DAB_FREQUENCY_ID = + new ProgramSelector.Identifier(ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY, + /* value= */ 220_352); + private static final ProgramSelector TEST_DAB_SELECTOR = TestUtils.makeProgramSelector( + ProgramSelector.PROGRAM_TYPE_DAB, TEST_DAB_SID_ID, + new ProgramSelector.Identifier[]{TEST_DAB_FREQUENCY_ID, TEST_DAB_ENSEMBLE_ID}); + private static final RadioManager.ProgramInfo TEST_DAB_INFO = TestUtils.makeProgramInfo( + TEST_DAB_SELECTOR, TEST_QUALITY); @Override protected void initializeSession(StaticMockitoSessionBuilder builder) { @@ -126,18 +147,18 @@ public class StartProgramListUpdatesFanoutTest extends ExtendedRadioMockitoTestC // Initiate a program list update from the HAL side and verify both connected AIDL clients // receive the update. - updateHalProgramInfo(true, Arrays.asList(mAmFmInfo, mRdsInfo), null); + updateHalProgramInfo(true, Arrays.asList(TEST_AM_FM_INFO, TEST_RDS_INFO), null); for (int i = 0; i < 2; i++) { verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[i], true, Arrays.asList( - mAmFmInfo, mRdsInfo), null); + TEST_AM_FM_INFO, TEST_RDS_INFO), null); } // Repeat with a non-purging update. - updateHalProgramInfo(false, Arrays.asList(mModifiedAmFmInfo), - Arrays.asList(mRdsIdentifier)); + updateHalProgramInfo(false, Arrays.asList(TEST_AM_FM_MODIFIED_INFO), + Arrays.asList(TEST_RDS_ID)); for (int i = 0; i < 2; i++) { verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[i], false, - Arrays.asList(mModifiedAmFmInfo), Arrays.asList(mRdsIdentifier)); + Arrays.asList(TEST_AM_FM_MODIFIED_INFO), Arrays.asList(TEST_RDS_UNIQUE_ID)); } // Now start updates on the 3rd client. Verify the HAL function has not been called again @@ -145,19 +166,19 @@ public class StartProgramListUpdatesFanoutTest extends ExtendedRadioMockitoTestC mTunerSessions[2].startProgramListUpdates(aidlFilter); verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(any()); verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[2], true, - Arrays.asList(mModifiedAmFmInfo), null); + Arrays.asList(TEST_AM_FM_MODIFIED_INFO), null); } @Test public void testFiltering() throws RemoteException { // Open 4 clients that will use the following filters: - // [0]: ID mRdsIdentifier, modifications excluded + // [0]: ID TEST_RDS_ID, modifications excluded // [1]: No categories, modifications excluded // [2]: Type IDENTIFIER_TYPE_AMFM_FREQUENCY, modifications excluded // [3]: Type IDENTIFIER_TYPE_AMFM_FREQUENCY, modifications included openAidlClients(4); ProgramList.Filter idFilter = new ProgramList.Filter(new HashSet<Integer>(), - new HashSet<ProgramSelector.Identifier>(Arrays.asList(mRdsIdentifier)), true, true); + new HashSet<ProgramSelector.Identifier>(Arrays.asList(TEST_RDS_ID)), true, true); ProgramList.Filter categoryFilter = new ProgramList.Filter(new HashSet<Integer>(), new HashSet<ProgramSelector.Identifier>(), false, true); ProgramList.Filter typeFilterWithoutModifications = new ProgramList.Filter( @@ -188,41 +209,40 @@ public class StartProgramListUpdatesFanoutTest extends ExtendedRadioMockitoTestC halFilter.excludeModifications = false; verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(halFilter); - // Adding mRdsInfo should update clients [0] and [1]. - updateHalProgramInfo(false, Arrays.asList(mRdsInfo), null); - verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], false, Arrays.asList(mRdsInfo), - null); - verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], false, Arrays.asList(mRdsInfo), - null); - - // Adding mAmFmInfo should update clients [1], [2], and [3]. - updateHalProgramInfo(false, Arrays.asList(mAmFmInfo), null); - verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], false, Arrays.asList(mAmFmInfo), - null); - verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[2], false, Arrays.asList(mAmFmInfo), - null); - verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[3], false, Arrays.asList(mAmFmInfo), - null); + // Adding TEST_RDS_INFO should update clients [0] and [1]. + updateHalProgramInfo(false, Arrays.asList(TEST_RDS_INFO), null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], false, + Arrays.asList(TEST_RDS_INFO), null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], false, + Arrays.asList(TEST_RDS_INFO), null); + + // Adding TEST_AM_FM_INFO should update clients [1], [2], and [3]. + updateHalProgramInfo(false, Arrays.asList(TEST_AM_FM_INFO), null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], false, + Arrays.asList(TEST_AM_FM_INFO), null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[2], false, + Arrays.asList(TEST_AM_FM_INFO), null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[3], false, + Arrays.asList(TEST_AM_FM_INFO), null); - // Modifying mAmFmInfo to mModifiedAmFmInfo should update only [3]. - updateHalProgramInfo(false, Arrays.asList(mModifiedAmFmInfo), null); + // Modifying TEST_AM_FM_INFO to TEST_AM_FM_MODIFIED_INFO should update only [3]. + updateHalProgramInfo(false, Arrays.asList(TEST_AM_FM_MODIFIED_INFO), null); verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[3], false, - Arrays.asList(mModifiedAmFmInfo), null); + Arrays.asList(TEST_AM_FM_MODIFIED_INFO), null); - // Adding mDabEnsembleInfo should not update any client. - updateHalProgramInfo(false, Arrays.asList(mDabEnsembleInfo), null); + updateHalProgramInfo(false, Arrays.asList(TEST_DAB_INFO), null); verify(mAidlTunerCallbackMocks[0], CB_TIMEOUT.times(1)).onProgramListUpdated(any()); - verify(mAidlTunerCallbackMocks[1], CB_TIMEOUT.times(2)).onProgramListUpdated(any()); + verify(mAidlTunerCallbackMocks[1], CB_TIMEOUT.times(3)).onProgramListUpdated(any()); verify(mAidlTunerCallbackMocks[2], CB_TIMEOUT.times(2)).onProgramListUpdated(any()); verify(mAidlTunerCallbackMocks[3], CB_TIMEOUT.times(2)).onProgramListUpdated(any()); } @Test public void testClientClosing() throws RemoteException { - // Open 2 clients that use different filters that are both sensitive to mAmFmIdentifier. + // Open 2 clients that use different filters that are both sensitive to TEST_AM_FM_ID. openAidlClients(2); ProgramList.Filter idFilter = new ProgramList.Filter(new HashSet<Integer>(), - new HashSet<ProgramSelector.Identifier>(Arrays.asList(mAmFmIdentifier)), true, + new HashSet<ProgramSelector.Identifier>(Arrays.asList(TEST_AM_FM_ID)), true, false); ProgramList.Filter typeFilter = new ProgramList.Filter( new HashSet<Integer>(Arrays.asList(ProgramSelector.IDENTIFIER_TYPE_AMFM_FREQUENCY)), @@ -237,23 +257,24 @@ public class StartProgramListUpdatesFanoutTest extends ExtendedRadioMockitoTestC halFilter.identifiers.clear(); verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(halFilter); - // Update the HAL with mAmFmInfo, and verify both clients are updated. - updateHalProgramInfo(true, Arrays.asList(mAmFmInfo), null); - verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], true, Arrays.asList(mAmFmInfo), - null); - verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], true, Arrays.asList(mAmFmInfo), - null); + // Update the HAL with TEST_AM_FM_INFO, and verify both clients are updated. + updateHalProgramInfo(true, Arrays.asList(TEST_AM_FM_INFO), null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], true, + Arrays.asList(TEST_AM_FM_INFO), null); + verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], true, + Arrays.asList(TEST_AM_FM_INFO), null); // Stop updates on the first client and verify the HAL filter is updated. mTunerSessions[0].stopProgramListUpdates(); verify(mHalTunerSessionMock, times(1)).startProgramListUpdates(Convert.programFilterToHal( typeFilter)); - // Update the HAL with mModifiedAmFmInfo, and verify only the remaining client is updated. - updateHalProgramInfo(true, Arrays.asList(mModifiedAmFmInfo), null); + // Update the HAL with TEST_AM_FM_MODIFIED_INFO, and verify only the remaining client is + // updated. + updateHalProgramInfo(true, Arrays.asList(TEST_AM_FM_MODIFIED_INFO), null); verify(mAidlTunerCallbackMocks[0], CB_TIMEOUT.times(1)).onProgramListUpdated(any()); verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[1], true, - Arrays.asList(mModifiedAmFmInfo), null); + Arrays.asList(TEST_AM_FM_MODIFIED_INFO), null); // Close the other client without explicitly stopping updates, and verify HAL updates are // stopped as well. @@ -269,15 +290,15 @@ public class StartProgramListUpdatesFanoutTest extends ExtendedRadioMockitoTestC // Verify the AIDL client receives all types of updates (e.g. a new program, an update to // that program, and a category). - updateHalProgramInfo(true, Arrays.asList(mAmFmInfo, mRdsInfo), null); + updateHalProgramInfo(true, Arrays.asList(TEST_AM_FM_INFO, TEST_RDS_INFO), null); verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], true, Arrays.asList( - mAmFmInfo, mRdsInfo), null); - updateHalProgramInfo(false, Arrays.asList(mModifiedAmFmInfo), null); + TEST_AM_FM_INFO, TEST_RDS_INFO), null); + updateHalProgramInfo(false, Arrays.asList(TEST_AM_FM_MODIFIED_INFO), null); verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], false, - Arrays.asList(mModifiedAmFmInfo), null); - updateHalProgramInfo(false, Arrays.asList(mDabEnsembleInfo), null); + Arrays.asList(TEST_AM_FM_MODIFIED_INFO), null); + updateHalProgramInfo(false, Arrays.asList(TEST_DAB_INFO), null); verifyAidlClientReceivedChunk(mAidlTunerCallbackMocks[0], false, - Arrays.asList(mDabEnsembleInfo), null); + Arrays.asList(TEST_DAB_INFO), null); // Verify closing the AIDL session also stops HAL updates. mTunerSessions[0].close(); @@ -313,12 +334,12 @@ public class StartProgramListUpdatesFanoutTest extends ExtendedRadioMockitoTestC private void verifyAidlClientReceivedChunk(android.hardware.radio.ITunerCallback clientMock, boolean purge, List<RadioManager.ProgramInfo> modified, - List<ProgramSelector.Identifier> removed) throws RemoteException { + List<UniqueProgramIdentifier> removed) throws RemoteException { HashSet<RadioManager.ProgramInfo> modifiedSet = new HashSet<>(); if (modified != null) { modifiedSet.addAll(modified); } - HashSet<ProgramSelector.Identifier> removedSet = new HashSet<>(); + HashSet<UniqueProgramIdentifier> removedSet = new HashSet<>(); if (removed != null) { removedSet.addAll(removed); } diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TestUtils.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TestUtils.java index d4ca8d4c96d3..0b1614114869 100644 --- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TestUtils.java +++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/hal2/TestUtils.java @@ -45,6 +45,23 @@ final class TestUtils { static RadioManager.ProgramInfo makeProgramInfo(ProgramSelector selector, ProgramSelector.Identifier logicallyTunedTo, ProgramSelector.Identifier physicallyTunedTo, int signalQuality) { + if (logicallyTunedTo == null) { + logicallyTunedTo = selector.getPrimaryId(); + } + if (physicallyTunedTo == null) { + if (selector.getPrimaryId().getType() + == ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT) { + for (int i = 0; i < selector.getSecondaryIds().length; i++) { + if (selector.getSecondaryIds()[i].getType() + == ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY) { + physicallyTunedTo = selector.getSecondaryIds()[i]; + break; + } + } + } else { + physicallyTunedTo = selector.getPrimaryId(); + } + } return new RadioManager.ProgramInfo(selector, logicallyTunedTo, physicallyTunedTo, /* relatedContents= */ null, /* infoFlags= */ 0, signalQuality, @@ -52,14 +69,8 @@ final class TestUtils { } static RadioManager.ProgramInfo makeProgramInfo(ProgramSelector selector, int signalQuality) { - return makeProgramInfo(selector, selector.getPrimaryId(), selector.getPrimaryId(), - signalQuality); - } - - static RadioManager.ProgramInfo makeProgramInfo(int programType, - ProgramSelector.Identifier identifier, int signalQuality) { - return makeProgramInfo(makeProgramSelector(programType, identifier), - /* logicallyTunedTo= */ null, /* physicallyTunedTo= */ null, signalQuality); + return makeProgramInfo(selector, /* logicallyTunedTo= */ null, + /* physicallyTunedTo= */ null, signalQuality); } static ProgramSelector makeFmSelector(long freq) { @@ -70,8 +81,12 @@ final class TestUtils { static ProgramSelector makeProgramSelector(int programType, ProgramSelector.Identifier identifier) { - return new ProgramSelector(programType, identifier, /* secondaryIds= */ null, - /* vendorIds= */ null); + return makeProgramSelector(programType, identifier, /* secondaryIds= */ null); + } + + static ProgramSelector makeProgramSelector(int programType, + ProgramSelector.Identifier primaryId, ProgramSelector.Identifier[] secondaryIds) { + return new ProgramSelector(programType, primaryId, secondaryIds, /* vendorIds= */ null); } static ProgramInfo programInfoToHal(RadioManager.ProgramInfo info) { @@ -79,6 +94,21 @@ final class TestUtils { // function only copies fields that are set by makeProgramInfo(). ProgramInfo hwInfo = new ProgramInfo(); hwInfo.selector = Convert.programSelectorToHal(info.getSelector()); + hwInfo.logicallyTunedTo = hwInfo.selector.primaryId; + if (info.getSelector().getPrimaryId().getType() + == ProgramSelector.IDENTIFIER_TYPE_DAB_SID_EXT) { + for (int i = 0; i < info.getSelector().getSecondaryIds().length; i++) { + if (info.getSelector().getSecondaryIds()[i].getType() + == ProgramSelector.IDENTIFIER_TYPE_DAB_FREQUENCY) { + hwInfo.physicallyTunedTo = Convert.programIdentifierToHal(info.getSelector() + .getSecondaryIds()[i]); + break; + } + } + } else { + hwInfo.physicallyTunedTo = Convert.programIdentifierToHal(info.getSelector() + .getPrimaryId()); + } hwInfo.signalQuality = info.getSignalStrength(); return hwInfo; } diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java index 0778311e98bd..819178f40451 100644 --- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java +++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java @@ -99,7 +99,7 @@ public class ActivityThreadTest { // The first sequence number to try with. Use a large number to avoid conflicts with the first a // few sequence numbers the framework used to launch the test activity. - private static final int BASE_SEQ = 10000; + private static final int BASE_SEQ = 10000000; @Rule public final ActivityTestRule<TestActivity> mActivityTestRule = diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json index 6057852a7e4b..721a2db9d6d3 100644 --- a/data/etc/services.core.protolog.json +++ b/data/etc/services.core.protolog.json @@ -3067,6 +3067,12 @@ "group": "WM_DEBUG_REMOTE_ANIMATIONS", "at": "com\/android\/server\/wm\/RemoteAnimationController.java" }, + "643263584": { + "message": "Content Recording: Apply transformations of shift %d x %d, scale %f, crop %d x %d for display %d", + "level": "VERBOSE", + "group": "WM_DEBUG_CONTENT_RECORDING", + "at": "com\/android\/server\/wm\/ContentRecorder.java" + }, "644675193": { "message": "Real start recents", "level": "DEBUG", diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index a4c655c8ce55..1ff5a3d46f8e 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -1779,7 +1779,7 @@ public final class Bitmap implements Parcelable { * If the bitmap's internal config is in one of the public formats, return * that config, otherwise return null. */ - @NonNull + @Nullable public final Config getConfig() { if (mRecycled) { Log.w(TAG, "Called getConfig() on a recycle()'d bitmap! This is undefined behavior!"); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java index 9b8006362c79..4640106b5f1c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java @@ -245,8 +245,8 @@ class ActivityEmbeddingAnimationSpec { private boolean shouldShowBackdrop(@NonNull TransitionInfo info, @NonNull TransitionInfo.Change change) { - final Animation a = loadAttributeAnimation(info.getType(), info, change, - WALLPAPER_TRANSITION_NONE, mTransitionAnimation, false); + final Animation a = loadAttributeAnimation(info, change, WALLPAPER_TRANSITION_NONE, + mTransitionAnimation, false); return a != null && a.getShowBackdrop(); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 093ecb1e3ade..d10de833ab89 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -131,6 +131,7 @@ public class BubbleStackView extends FrameLayout private static final int EXPANDED_VIEW_ALPHA_ANIMATION_DURATION = 150; + /** Should be kept in sync with value in TaskbarScrimViewController. */ private static final float SCRIM_ALPHA = 0.32f; /** Minimum alpha value for scrim when alpha is being changed via drag */ diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index f90ee586e696..991b699161ea 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -43,6 +43,7 @@ import android.app.ActivityOptions; import android.app.ActivityTaskManager; import android.app.PendingIntent; import android.app.TaskInfo; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.ShortcutInfo; @@ -814,21 +815,22 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, final String packageName1 = SplitScreenUtils.getPackageName(intent); final String packageName2 = getPackageName(reverseSplitPosition(position)); final int userId2 = getUserId(reverseSplitPosition(position)); + final ComponentName component = intent.getIntent().getComponent(); + + // To prevent accumulating large number of instances in the background, reuse task + // in the background. If we don't explicitly reuse, new may be created even if the app + // isn't multi-instance because WM won't automatically remove/reuse the previous instance + final ActivityManager.RecentTaskInfo taskInfo = mRecentTasksOptional + .map(recentTasks -> recentTasks.findTaskInBackground(component, userId1)) + .orElse(null); + if (taskInfo != null) { + startTask(taskInfo.taskId, position, options); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, + "Start task in background"); + return; + } if (samePackage(packageName1, packageName2, userId1, userId2)) { if (supportMultiInstancesSplit(packageName1)) { - // To prevent accumulating large number of instances in the background, reuse task - // in the background with priority. - final ActivityManager.RecentTaskInfo taskInfo = mRecentTasksOptional - .map(recentTasks -> recentTasks.findTaskInBackground( - intent.getIntent().getComponent(), userId1)) - .orElse(null); - if (taskInfo != null) { - startTask(taskInfo.taskId, position, options); - ProtoLog.v(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, - "Start task in background"); - return; - } - // Flag with MULTIPLE_TASK if this is launching the same activity into both sides of // the split and there is no reusable background task. fillInIntent.addFlags(FLAG_ACTIVITY_MULTIPLE_TASK); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java index d310ae32993c..7df658e6c9db 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java @@ -37,12 +37,8 @@ import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED; import static android.view.WindowManager.TRANSIT_CHANGE; -import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; -import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_RELAUNCH; -import static android.view.WindowManager.TRANSIT_TO_FRONT; -import static android.window.TransitionInfo.FLAGS_IS_NON_APP_WINDOW; import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED; import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_OWNER_THUMBNAIL; import static android.window.TransitionInfo.FLAG_CROSS_PROFILE_WORK_THUMBNAIL; @@ -338,10 +334,6 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { boolean isDisplayRotationAnimationStarted = false; final boolean isDreamTransition = isDreamTransition(info); final boolean isOnlyTranslucent = isOnlyTranslucent(info); - final boolean isActivityReplace = checkActivityReplacement(info, startTransaction); - // Some patterns (eg. activity "replacement") require us to re-interpret the type - @WindowManager.TransitionType final int transitType = - isActivityReplace ? TRANSIT_OPEN : info.getType(); for (int i = info.getChanges().size() - 1; i >= 0; --i) { final TransitionInfo.Change change = info.getChanges().get(i); @@ -438,8 +430,7 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { // Don't animate anything that isn't independent. if (!TransitionInfo.isIndependent(change, info)) continue; - Animation a = loadAnimation(transitType, info, change, wallpaperTransit, - isDreamTransition); + Animation a = loadAnimation(info, change, wallpaperTransit, isDreamTransition); if (a != null) { if (isTask) { final boolean isTranslucent = (change.getFlags() & FLAG_TRANSLUCENT) != 0; @@ -613,53 +604,6 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { return (translucentOpen + translucentClose) > 0; } - /** - * Checks for an edge-case where an activity calls finish() followed immediately by - * startActivity() to "replace" itself. If in this case, it will swap the layer of the - * close/open activities and return `true`. This way, we pretend like we are just "opening" - * the new activity. - */ - private static boolean checkActivityReplacement(@NonNull TransitionInfo info, - SurfaceControl.Transaction t) { - if (info.getType() != TRANSIT_CLOSE) { - return false; - } - int closing = -1; - int opening = -1; - for (int i = info.getChanges().size() - 1; i >= 0; --i) { - final TransitionInfo.Change change = info.getChanges().get(i); - if ((change.getTaskInfo() != null || change.hasFlags(FLAG_IS_DISPLAY)) - && !TransitionUtil.isOrderOnly(change)) { - // This isn't an activity-level transition. - return false; - } - if (change.getTaskInfo() != null - && change.hasFlags(FLAG_IS_DISPLAY | FLAGS_IS_NON_APP_WINDOW)) { - // Ignore non-activity containers. - continue; - } - if (TransitionUtil.isClosingType(change.getMode())) { - closing = i; - } else if (change.getMode() == TRANSIT_OPEN) { - // OPEN implies that it is a new launch. If going "back" the opening app will be - // TO_FRONT - opening = i; - } else if (change.getMode() == TRANSIT_TO_FRONT) { - // Normal "going back", so not a replacement. - return false; - } - } - if (closing < 0 || opening < 0) { - return false; - } - // Swap the opening and closing z-orders since we're swapping the transit type. - final int numChanges = info.getChanges().size(); - final int zSplitLine = numChanges + 1; - t.setLayer(info.getChanges().get(opening).getLeash(), zSplitLine + numChanges - opening); - t.setLayer(info.getChanges().get(closing).getLeash(), zSplitLine - closing); - return true; - } - @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @@ -712,11 +656,12 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { } @Nullable - private Animation loadAnimation(int type, @NonNull TransitionInfo info, + private Animation loadAnimation(@NonNull TransitionInfo info, @NonNull TransitionInfo.Change change, int wallpaperTransit, boolean isDreamTransition) { Animation a; + final int type = info.getType(); final int flags = info.getFlags(); final int changeMode = change.getMode(); final int changeFlags = change.getFlags(); @@ -771,8 +716,8 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { // If there's a scene-transition, then jump-cut. return null; } else { - a = loadAttributeAnimation(type, info, change, wallpaperTransit, mTransitionAnimation, - isDreamTransition); + a = loadAttributeAnimation( + info, change, wallpaperTransit, mTransitionAnimation, isDreamTransition); } if (a != null) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java index c99911de5291..d07d2b7b6db9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/TransitionAnimationHelper.java @@ -45,7 +45,6 @@ import android.graphics.Rect; import android.graphics.Shader; import android.view.Surface; import android.view.SurfaceControl; -import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.Transformation; import android.window.ScreenCapture; @@ -62,10 +61,10 @@ public class TransitionAnimationHelper { /** Loads the animation that is defined through attribute id for the given transition. */ @Nullable - public static Animation loadAttributeAnimation(@WindowManager.TransitionType int type, - @NonNull TransitionInfo info, @NonNull TransitionInfo.Change change, - int wallpaperTransit, @NonNull TransitionAnimation transitionAnimation, - boolean isDreamTransition) { + public static Animation loadAttributeAnimation(@NonNull TransitionInfo info, + @NonNull TransitionInfo.Change change, int wallpaperTransit, + @NonNull TransitionAnimation transitionAnimation, boolean isDreamTransition) { + final int type = info.getType(); final int changeMode = change.getMode(); final int changeFlags = change.getFlags(); final boolean enter = TransitionUtil.isOpeningType(changeMode); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java index 568db919818c..99cd4f391153 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java @@ -36,6 +36,7 @@ import static org.mockito.ArgumentMatchers.isA; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -218,8 +219,7 @@ public class SplitScreenControllerTests extends ShellTestCase { } @Test - public void startIntent_multiInstancesSupported_startTaskInBackgroundBeforeSplitActivated() { - doReturn(true).when(mSplitScreenController).supportMultiInstancesSplit(any()); + public void startIntent_multiInstancesNotSupported_startTaskInBackgroundBeforeSplitActivated() { doNothing().when(mSplitScreenController).startTask(anyInt(), anyInt(), any()); Intent startIntent = createStartIntent("startActivity"); PendingIntent pendingIntent = @@ -237,6 +237,8 @@ public class SplitScreenControllerTests extends ShellTestCase { verify(mSplitScreenController).startTask(anyInt(), eq(SPLIT_POSITION_TOP_OR_LEFT), isNull()); + verify(mSplitScreenController, never()).supportMultiInstancesSplit(any()); + verify(mStageCoordinator, never()).switchSplitPosition(any()); } @Test diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 1ee5aa36740c..8e9c07996f83 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -931,8 +931,7 @@ public class MediaPlayer extends PlayerBase * @return a MediaPlayer object, or null if creation failed */ public static MediaPlayer create(Context context, Uri uri, SurfaceHolder holder) { - int s = AudioSystem.newAudioSessionId(); - return create(context, uri, holder, null, s > 0 ? s : 0); + return create(context, uri, holder, null, AudioSystem.AUDIO_SESSION_ALLOCATE); } /** @@ -994,8 +993,7 @@ public class MediaPlayer extends PlayerBase * @return a MediaPlayer object, or null if creation failed */ public static MediaPlayer create(Context context, int resid) { - int s = AudioSystem.newAudioSessionId(); - return create(context, resid, null, s > 0 ? s : 0); + return create(context, resid, null, AudioSystem.AUDIO_SESSION_ALLOCATE); } /** diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerUnitTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerUnitTest.java index f812d5fa1c20..f27a5687ee36 100644 --- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerUnitTest.java +++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/MediaPlayerUnitTest.java @@ -30,6 +30,7 @@ import static org.mockito.Mockito.when; import android.companion.virtual.VirtualDeviceManager; import android.content.Context; +import android.media.AudioAttributes; import android.media.AudioManager; import android.media.MediaPlayer; import android.test.mock.MockContext; @@ -37,6 +38,8 @@ import android.test.mock.MockContext; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; +import com.android.mediaframeworktest.R; + import org.junit.Test; import org.junit.runner.RunWith; @@ -45,6 +48,8 @@ import org.junit.runner.RunWith; public class MediaPlayerUnitTest { private static final int TEST_VIRTUAL_DEVICE_ID = 42; + private static final AudioAttributes AUDIO_ATTRIBUTES_MEDIA = + new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build(); @Test public void testConstructionWithContext_virtualDeviceDefaultAudioPolicy() { @@ -89,6 +94,49 @@ public class MediaPlayerUnitTest { assertEquals(anotherSessionId, mediaPlayer.getAudioSessionId()); } + @Test + public void testCreateFromResource_virtualDeviceDefaultAudioPolicy() { + int vdmPlaybackSessionId = getContext().getSystemService( + AudioManager.class).generateAudioSessionId(); + VirtualDeviceManager mockVdm = getMockVirtualDeviceManager(TEST_VIRTUAL_DEVICE_ID, + vdmPlaybackSessionId, DEVICE_POLICY_DEFAULT); + Context virtualDeviceContext = getVirtualDeviceMockContext(TEST_VIRTUAL_DEVICE_ID, mockVdm); + + MediaPlayer mediaPlayer = MediaPlayer.create(virtualDeviceContext, R.raw.testmp3); + + assertNotEquals(vdmPlaybackSessionId, mediaPlayer.getAudioSessionId()); + assertTrue(mediaPlayer.getAudioSessionId() > 0); + } + + @Test + public void testCreateFromResource_virtualDeviceCustomAudioPolicy() { + int vdmPlaybackSessionId = getContext().getSystemService( + AudioManager.class).generateAudioSessionId(); + VirtualDeviceManager mockVdm = getMockVirtualDeviceManager(TEST_VIRTUAL_DEVICE_ID, + vdmPlaybackSessionId, DEVICE_POLICY_CUSTOM); + Context virtualDeviceContext = getVirtualDeviceMockContext(TEST_VIRTUAL_DEVICE_ID, mockVdm); + + MediaPlayer mediaPlayer = MediaPlayer.create(virtualDeviceContext, R.raw.testmp3); + + assertEquals(vdmPlaybackSessionId, mediaPlayer.getAudioSessionId()); + } + + @Test + public void testCreateFromResource_explicitSessionIdOverridesContext() { + int vdmPlaybackSessionId = getContext().getSystemService( + AudioManager.class).generateAudioSessionId(); + int anotherSessionId = getContext().getSystemService( + AudioManager.class).generateAudioSessionId(); + VirtualDeviceManager mockVdm = getMockVirtualDeviceManager(TEST_VIRTUAL_DEVICE_ID, + vdmPlaybackSessionId, DEVICE_POLICY_CUSTOM); + Context virtualDeviceContext = getVirtualDeviceMockContext(TEST_VIRTUAL_DEVICE_ID, mockVdm); + + MediaPlayer mediaPlayer = MediaPlayer.create(virtualDeviceContext, R.raw.testmp3, + AUDIO_ATTRIBUTES_MEDIA, anotherSessionId); + + assertEquals(anotherSessionId, mediaPlayer.getAudioSessionId()); + } + private Context getContext() { return InstrumentationRegistry.getInstrumentation().getContext(); } @@ -98,6 +146,7 @@ public class MediaPlayerUnitTest { when(mockContext.getDeviceId()).thenReturn(deviceId); when(mockContext.getSystemService(VirtualDeviceManager.class)).thenReturn(vdm); when(mockContext.getAttributionSource()).thenReturn(getContext().getAttributionSource()); + when(mockContext.getResources()).thenReturn(getContext().getResources()); return mockContext; } diff --git a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java index e46db75f633e..33907ece5a7c 100644 --- a/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java +++ b/packages/SettingsLib/Tile/src/com/android/settingslib/drawer/TileUtils.java @@ -344,7 +344,9 @@ public class TileUtils { continue; } final ProviderInfo providerInfo = resolved.providerInfo; - final List<Bundle> entryData = getEntryDataFromProvider(context, + final List<Bundle> entryData = getEntryDataFromProvider( + // Build new context so the entry data is retrieved for the queried user. + context.createContextAsUser(user, 0 /* flags */), providerInfo.authority); if (entryData == null || entryData.isEmpty()) { continue; diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java index 20864664e512..a8063e84cfca 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java @@ -35,6 +35,7 @@ import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -52,6 +53,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.ProviderInfo; import android.content.pm.ResolveInfo; import android.content.res.Resources; +import android.net.Uri; import android.os.Bundle; import android.os.UserHandle; import android.os.UserManager; @@ -69,6 +71,8 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import org.robolectric.annotation.Implementation; import org.robolectric.annotation.Implements; +import org.robolectric.shadow.api.Shadow; +import org.robolectric.util.ReflectionHelpers; import java.util.ArrayList; import java.util.Arrays; @@ -88,6 +92,10 @@ public class TileUtilsTest { private UserManager mUserManager; @Mock private ContentResolver mContentResolver; + @Mock + private Context mUserContext; + @Mock + private ContentResolver mUserContentResolver; private static final String URI_GET_SUMMARY = "content://authority/text/summary"; private static final String URI_GET_ICON = "content://authority/icon/my_icon"; @@ -104,6 +112,8 @@ public class TileUtilsTest { mContentResolver = spy(application.getContentResolver()); when(mContext.getContentResolver()).thenReturn(mContentResolver); when(mContext.getPackageName()).thenReturn("com.android.settings"); + when(mUserContext.getContentResolver()).thenReturn(mUserContentResolver); + ShadowTileUtils.sCallRealEntryDataFromProvider = false; } @Test @@ -375,6 +385,30 @@ public class TileUtilsTest { } @Test + public void loadTilesForAction_forUserProvider_getEntryDataFromProvider_inContextOfGivenUser() { + ShadowTileUtils.sCallRealEntryDataFromProvider = true; + UserHandle userHandle = new UserHandle(10); + + doReturn(mUserContext).when(mContext).createContextAsUser(eq(userHandle), anyInt()); + + Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>(); + List<Tile> outTiles = new ArrayList<>(); + List<ResolveInfo> info = new ArrayList<>(); + ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON, + URI_GET_SUMMARY, null, 123, PROFILE_ALL); + info.add(resolveInfo); + + when(mPackageManager.queryIntentContentProvidersAsUser(any(Intent.class), anyInt(), + anyInt())).thenReturn(info); + + TileUtils.loadTilesForAction(mContext, userHandle, IA_SETTINGS_ACTION, + addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */); + + verify(mUserContentResolver, atLeastOnce()) + .acquireUnstableProvider(any(Uri.class)); + } + + @Test public void loadTilesForAction_withPendingIntent_updatesPendingIntentMap() { Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>(); List<Tile> outTiles = new ArrayList<>(); @@ -472,8 +506,17 @@ public class TileUtilsTest { private static Bundle sMetaData; + private static boolean sCallRealEntryDataFromProvider; + @Implementation protected static List<Bundle> getEntryDataFromProvider(Context context, String authority) { + if (sCallRealEntryDataFromProvider) { + return Shadow.directlyOn( + TileUtils.class, + "getEntryDataFromProvider", + ReflectionHelpers.ClassParameter.from(Context.class, context), + ReflectionHelpers.ClassParameter.from(String.class, authority)); + } return Arrays.asList(sMetaData); } diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index a8922694e7a2..78da5a699759 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -6,6 +6,7 @@ dsandler@android.com aaliomer@google.com aaronjli@google.com +achalke@google.com acul@google.com adamcohen@google.com aioana@google.com @@ -72,6 +73,7 @@ omarmt@google.com patmanning@google.com peanutbutter@google.com peskal@google.com +petrcermak@google.com pinyaoting@google.com pixel@google.com pomini@google.com @@ -82,13 +84,17 @@ santie@google.com shanh@google.com snoeberger@google.com steell@google.com +stevenckng@google.com stwu@google.com syeonlee@google.com sunnygoyal@google.com thiruram@google.com +tkachenkoi@google.com tracyzhou@google.com tsuji@google.com twickham@google.com +vadimt@google.com +vanjan@google.com victortulias@google.com winsonc@google.com wleshner@google.com diff --git a/packages/SystemUI/TEST_MAPPING b/packages/SystemUI/TEST_MAPPING index 969c14821350..cb9e9ee903c5 100644 --- a/packages/SystemUI/TEST_MAPPING +++ b/packages/SystemUI/TEST_MAPPING @@ -1,47 +1,23 @@ { - // Curious where your @Scenario tests will run? + // Curious where your @Scenario tests are running? // // @Ignore: Will not run in any configuration // - // @FlakyTest: Tests that don't block pre/postsubmit but are staged to run known failures + // @FlakyTest: Tests that don't block pre/postsubmit but are staged to run known failures. + // Tests will run in postsubmit on sysui-e2e-staged suite. // - // @Postsubmit: Runs in platinum suite and blocks droidfood in postsubmit // - // @PlatinumTest: As of May, 2023, running in postsubmit. Set to run in presubmit as part of - // v2/android-platinum/suite-test-mapping-platinum-sysui - // Please DO NOT annotate new or old tests with @PlatinumTest annotation without discussing - // with mdb:android-platinum + // @PlatinumTest: Marking your test with this annotation will put your tests in presubmit. + // Please DO NOT annotate new or old tests with @PlatinumTest annotation + // without discussing with mdb:android-platinum // - // As of May, 2023, If you don't use @Postsubmit, your new test will immediately - // block presubmit, which is probably NOT what you want. This will change effectively once - // we move to @PlatinumTest annotation. + // @Postsubmit: Do not use this annotation for e2e tests. This won't have any affect. + + // For all other e2e tests which are not platinum, they run in sysui-silver suite,that + // primarily runs in postsubmit with an exception to e2e test related changes. + // If you want to see one shot place to monitor all e2e tests, look for + // sysui-e2e-staged suite. - // v2/sysui/test-mapping-presubmit-sysui_cloud-tf - "presubmit-sysui": [ - { - "name": "PlatformScenarioTests", - "options": [ - { - "include-filter": "android.platform.test.scenario.sysui" - }, - { - "include-annotation": "android.platform.test.scenario.annotation.Scenario" - }, - { - "exclude-annotation": "org.junit.Ignore" - }, - { - "exclude-annotation": "android.platform.test.annotations.Postsubmit" - }, - { - "exclude-annotation": "android.platform.test.annotations.FlakyTest" - }, - { - "exclude-annotation": "androidx.test.filters.FlakyTest" - } - ] - } - ], // v2/android-virtual-infra/test_mapping/presubmit-avd "presubmit": [ { @@ -138,31 +114,6 @@ ] } ], - "silver-sysui": [ - { - "name": "PlatformScenarioTests", - "options": [ - { - "include-filter": "android.platform.test.scenario.sysui" - }, - { - "include-annotation": "android.platform.test.scenario.annotation.Scenario" - }, - { - "exclude-annotation": "org.junit.Ignore" - }, - { - "exclude-annotation": "android.platform.test.annotations.PlatinumTest" - }, - { - "exclude-annotation": "android.platform.test.annotations.FlakyTest" - }, - { - "exclude-annotation": "androidx.test.filters.FlakyTest" - } - ] - } - ], "postsubmit": [ { "name": "SystemUIGoogleScreenshotTests", diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/ribbon/ui/composable/Ribbon.kt b/packages/SystemUI/compose/features/src/com/android/systemui/ribbon/ui/composable/Ribbon.kt new file mode 100644 index 000000000000..daa15929b9ce --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/ribbon/ui/composable/Ribbon.kt @@ -0,0 +1,92 @@ +/* + * Copyright 2023 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.systemui.ribbon.ui.composable + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.layout.layout +import com.android.compose.modifiers.thenIf +import kotlin.math.PI +import kotlin.math.cos +import kotlin.math.roundToInt +import kotlin.math.sin +import kotlin.math.tan + +/** + * Renders a "ribbon" at the bottom right corner of its container. + * + * The [content] is rendered leaning at an angle of [degrees] degrees (between `1` and `89`, + * inclusive), with an alpha of [alpha] (between `0f` and `1f`, inclusive). + * + * The background color of the strip can be modified by passing a value to the [backgroundColor] or + * `null` to remove the strip background. + * + * Note: this function assumes that it's been placed at the bottom right of its parent by its + * caller. It's the caller's responsibility to meet that assumption by actually placing this + * composable element at the bottom right. + */ +@Composable +fun BottomRightCornerRibbon( + content: @Composable () -> Unit, + modifier: Modifier = Modifier, + degrees: Int = 45, + alpha: Float = 0.6f, + backgroundColor: Color? = Color.Red, +) { + check(degrees in 1..89) + check(alpha in 0f..1f) + + val radians = degrees * (PI / 180) + + Box( + content = { content() }, + modifier = + modifier + .graphicsLayer { + this.alpha = alpha + + val w = size.width + val h = size.height + + val sine = sin(radians).toFloat() + val cosine = cos(radians).toFloat() + + translationX = (w - w * cosine + h * sine) / 2f + translationY = (h - w * sine + h * cosine) / 2f + rotationZ = 360f - degrees + } + .thenIf(backgroundColor != null) { Modifier.background(backgroundColor!!) } + .layout { measurable, constraints -> + val placeable = measurable.measure(constraints) + + val tangent = tan(radians) + val leftPadding = (placeable.measuredHeight / tangent).roundToInt() + val rightPadding = (placeable.measuredHeight * tangent).roundToInt() + + layout( + width = placeable.measuredWidth + leftPadding + rightPadding, + height = placeable.measuredHeight, + ) { + placeable.place(leftPadding, 0) + } + } + ) +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt index 019287d8d500..6a5a368b3599 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt @@ -18,14 +18,19 @@ package com.android.systemui.scene.ui.composable +import android.os.SystemProperties +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.pointer.PointerEventPass import androidx.compose.ui.input.pointer.motionEventSpy import androidx.compose.ui.input.pointer.pointerInput @@ -37,6 +42,7 @@ import com.android.compose.animation.scene.SceneTransitionLayoutState import com.android.compose.animation.scene.Swipe import com.android.compose.animation.scene.UserAction as SceneTransitionUserAction import com.android.compose.animation.scene.observableTransitionState +import com.android.systemui.ribbon.ui.composable.BottomRightCornerRibbon import com.android.systemui.scene.shared.model.Direction import com.android.systemui.scene.shared.model.ObservableTransitionState import com.android.systemui.scene.shared.model.SceneKey @@ -75,53 +81,70 @@ fun SceneContainer( val currentDestinations: Map<UserAction, SceneModel> by currentScene.destinationScenes().collectAsState() val state = remember { SceneTransitionLayoutState(currentSceneKey.toTransitionSceneKey()) } + val isRibbonEnabled = remember { SystemProperties.getBoolean("flexi.ribbon", false) } DisposableEffect(viewModel, state) { viewModel.setTransitionState(state.observableTransitionState().map { it.toModel() }) onDispose { viewModel.setTransitionState(null) } } - SceneTransitionLayout( - currentScene = currentSceneKey.toTransitionSceneKey(), - onChangeScene = viewModel::onSceneChanged, - transitions = SceneContainerTransitions, - state = state, - modifier = - modifier - .fillMaxSize() - .motionEventSpy { event -> viewModel.onMotionEvent(event) } - .pointerInput(Unit) { - awaitPointerEventScope { - while (true) { - awaitPointerEvent(PointerEventPass.Final) - viewModel.onMotionEventComplete() - } - } - } + Box( + modifier = Modifier.fillMaxSize(), ) { - sceneByKey.forEach { (sceneKey, composableScene) -> - scene( - key = sceneKey.toTransitionSceneKey(), - userActions = - if (sceneKey == currentSceneKey) { - currentDestinations - } else { - composableScene.destinationScenes().value + SceneTransitionLayout( + currentScene = currentSceneKey.toTransitionSceneKey(), + onChangeScene = viewModel::onSceneChanged, + transitions = SceneContainerTransitions, + state = state, + modifier = + modifier + .fillMaxSize() + .motionEventSpy { event -> viewModel.onMotionEvent(event) } + .pointerInput(Unit) { + awaitPointerEventScope { + while (true) { + awaitPointerEvent(PointerEventPass.Final) + viewModel.onMotionEventComplete() + } } - .map { (userAction, destinationSceneModel) -> - toTransitionModels(userAction, destinationSceneModel) - } - .toMap(), - ) { - with(composableScene) { - this@scene.Content( - modifier = - Modifier.element(sceneKey.toTransitionSceneKey().rootElementKey) - .fillMaxSize(), - ) + } + ) { + sceneByKey.forEach { (sceneKey, composableScene) -> + scene( + key = sceneKey.toTransitionSceneKey(), + userActions = + if (sceneKey == currentSceneKey) { + currentDestinations + } else { + composableScene.destinationScenes().value + } + .map { (userAction, destinationSceneModel) -> + toTransitionModels(userAction, destinationSceneModel) + } + .toMap(), + ) { + with(composableScene) { + this@scene.Content( + modifier = + Modifier.element(sceneKey.toTransitionSceneKey().rootElementKey) + .fillMaxSize(), + ) + } } } } + + if (isRibbonEnabled) { + BottomRightCornerRibbon( + content = { + Text( + text = "flexi\uD83E\uDD43", + color = Color.White, + ) + }, + modifier = Modifier.align(Alignment.BottomEnd), + ) + } } } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt index 5d6dd3b6bd01..23d3089d7be3 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/statusbar/phone/SystemUIDialogFactoryExt.kt @@ -48,10 +48,11 @@ import com.android.compose.theme.PlatformTheme */ fun SystemUIDialogFactory.create( context: Context = this.applicationContext, + theme: Int = SystemUIDialog.DEFAULT_THEME, dismissOnDeviceLock: Boolean = SystemUIDialog.DEFAULT_DISMISS_ON_DEVICE_LOCK, content: @Composable (SystemUIDialog) -> Unit, ): ComponentSystemUIDialog { - val dialog = create(context, dismissOnDeviceLock) + val dialog = create(context, theme, dismissOnDeviceLock) // Create the dialog so that it is properly constructed before we set the Compose content. // Otherwise, the ComposeView won't render properly. diff --git a/packages/SystemUI/res/layout/media_projection_app_selector.xml b/packages/SystemUI/res/layout/media_projection_app_selector.xml index e4749381243a..b77f78dfc644 100644 --- a/packages/SystemUI/res/layout/media_projection_app_selector.xml +++ b/packages/SystemUI/res/layout/media_projection_app_selector.xml @@ -20,10 +20,11 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" - androidprv:maxCollapsedHeight="0dp" + androidprv:maxCollapsedHeight="10000dp" androidprv:maxCollapsedHeightSmall="56dp" androidprv:maxWidth="@*android:dimen/chooser_width" android:id="@*android:id/contentPanel"> + <!-- maxCollapsedHeight above is huge, to make sure the layout is always expanded. --> <LinearLayout android:id="@*android:id/chooser_header" diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml index d8c808054fff..e48901ee0bb5 100644 --- a/packages/SystemUI/res/values/ids.xml +++ b/packages/SystemUI/res/values/ids.xml @@ -207,13 +207,14 @@ <!-- keyboard backlight indicator--> <item type="id" name="backlight_icon" /> + <!-- IDs for use in the keyguard/lockscreen scene --> <item type="id" name="keyguard_root_view" /> <item type="id" name="keyguard_indication_area" /> <item type="id" name="keyguard_indication_text" /> <item type="id" name="keyguard_indication_text_bottom" /> <item type="id" name="nssl_guideline" /> - <item type="id" name="nssl_top_barrier" /> - <item type="id" name="nssl_bottom_barrier" /> + <item type="id" name="nssl_placeholder" /> + <item type="id" name="aod_notification_icon_container" /> <item type="id" name="split_shade_guideline" /> <item type="id" name="lock_icon" /> <item type="id" name="lock_icon_bg" /> diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java index d89796005e25..11f95895338a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java @@ -18,7 +18,6 @@ package com.android.keyguard; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; - import static com.android.keyguard.KeyguardClockSwitch.LARGE; import static com.android.keyguard.KeyguardClockSwitch.SMALL; import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; @@ -42,6 +41,7 @@ import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.flags.FeatureFlags; +import com.android.systemui.flags.Flags; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor; import com.android.systemui.log.LogBuffer; @@ -240,7 +240,9 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS View nic = mView.findViewById( R.id.left_aligned_notification_icon_container); - nic.setVisibility(View.GONE); + if (nic != null) { + nic.setVisibility(View.GONE); + } } @Override @@ -307,7 +309,11 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS } int getNotificationIconAreaHeight() { - return mNotificationIconAreaController.getHeight(); + if (mFeatureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) { + return 0; + } else { + return mNotificationIconAreaController.getHeight(); + } } @Override @@ -518,10 +524,12 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS } private void updateAodIcons() { - NotificationIconContainer nic = (NotificationIconContainer) - mView.findViewById( - com.android.systemui.R.id.left_aligned_notification_icon_container); - mNotificationIconAreaController.setupAodIcons(nic); + if (!mFeatureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) { + NotificationIconContainer nic = (NotificationIconContainer) + mView.findViewById( + com.android.systemui.R.id.left_aligned_notification_icon_container); + mNotificationIconAreaController.setupAodIcons(nic); + } } private void setClock(ClockController clock) { diff --git a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt index ecc9d0ef7810..f730935e1b73 100644 --- a/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/display/ui/view/MirroringConfirmationDialog.kt @@ -34,7 +34,8 @@ class MirroringConfirmationDialog( context: Context, private val onStartMirroringClickListener: View.OnClickListener, private val onCancelMirroring: View.OnClickListener, -) : Dialog(context, R.style.Theme_SystemUI_Dialog) { + theme: Int = R.style.Theme_SystemUI_Dialog, +) : Dialog(context, theme) { private lateinit var mirrorButton: TextView private lateinit var dismissButton: TextView diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 1e5fcbe17557..2cc07fd74b95 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -802,4 +802,8 @@ object Flags { /** Enable haptic slider component in the brightness slider */ @JvmField val HAPTIC_BRIGHTNESS_SLIDER = unreleasedFlag("haptic_brightness_slider") + + // TODO(b/287205379): Tracking bug + @JvmField + val QS_CONTAINER_GRAPH_OPTIMIZER = unreleasedFlag( "qs_container_graph_optimizer") } diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt index b5b56b2b2108..6f25f7c1921a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt +++ b/packages/SystemUI/src/com/android/systemui/keyboard/backlight/ui/view/KeyboardBacklightDialog.kt @@ -44,7 +44,8 @@ class KeyboardBacklightDialog( context: Context, initialCurrentLevel: Int, initialMaxLevel: Int, -) : Dialog(context, R.style.Theme_SystemUI_Dialog) { + theme: Int = R.style.Theme_SystemUI_Dialog, +) : Dialog(context, theme) { private data class RootProperties( val cornerRadius: Float, diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt index 8b0b0ae543a7..9503f2c75052 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt @@ -177,14 +177,13 @@ object KeyguardRootViewBinder { oldRight: Int, oldBottom: Int ) { - val ksv = v.findViewById(R.id.keyguard_status_view) as View? - val lockIcon = v.findViewById(R.id.lock_icon_view) as View? + val nsslPlaceholder = v.findViewById(R.id.nssl_placeholder) as View? - if (ksv != null && lockIcon != null) { + if (nsslPlaceholder != null) { // After layout, ensure the notifications are positioned correctly viewModel.onSharedNotificationContainerPositionChanged( - ksv!!.top.toFloat() + ksv!!.height, - lockIcon!!.y + nsslPlaceholder.top.toFloat(), + nsslPlaceholder.bottom.toFloat(), ) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt index b0c969f54b82..15bb90915d94 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprint.kt @@ -22,6 +22,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags import com.android.systemui.keyguard.shared.model.KeyguardBlueprint +import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultAmbientIndicationAreaSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultLockIconSection @@ -50,6 +51,7 @@ constructor( defaultStatusViewSection: DefaultStatusViewSection, defaultNotificationStackScrollLayoutSection: DefaultNotificationStackScrollLayoutSection, splitShadeGuidelines: SplitShadeGuidelines, + aodNotificationIconsSection: AodNotificationIconsSection, private val featureFlags: FeatureFlags, ) : KeyguardBlueprint { override val id: String = DEFAULT @@ -64,6 +66,7 @@ constructor( defaultStatusViewSection, defaultNotificationStackScrollLayoutSection, splitShadeGuidelines, + aodNotificationIconsSection, ) override fun replaceViews( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt index bb3af6cc86a2..79a97fbd19df 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/blueprints/ShortcutsBesideUdfpsKeyguardBlueprint.kt @@ -20,6 +20,7 @@ package com.android.systemui.keyguard.ui.view.layout.blueprints import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.shared.model.KeyguardBlueprint import com.android.systemui.keyguard.ui.view.layout.sections.AlignShortcutsToUdfpsSection +import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultAmbientIndicationAreaSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultLockIconSection @@ -42,6 +43,7 @@ constructor( defaultStatusViewSection: DefaultStatusViewSection, splitShadeGuidelines: SplitShadeGuidelines, defaultNotificationStackScrollLayoutSection: DefaultNotificationStackScrollLayoutSection, + aodNotificationIconsSection: AodNotificationIconsSection, ) : KeyguardBlueprint { override val id: String = SHORTCUTS_BESIDE_UDFPS @@ -55,6 +57,7 @@ constructor( defaultStatusViewSection, defaultNotificationStackScrollLayoutSection, splitShadeGuidelines, + aodNotificationIconsSection, ) companion object { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt new file mode 100644 index 000000000000..ac11ba5b5ec6 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/AodNotificationIconsSection.kt @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2023 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.systemui.keyguard.ui.view.layout.sections + +import android.content.Context +import android.view.View +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.constraintlayout.widget.ConstraintSet +import androidx.constraintlayout.widget.ConstraintSet.BOTTOM +import androidx.constraintlayout.widget.ConstraintSet.END +import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID +import androidx.constraintlayout.widget.ConstraintSet.START +import androidx.constraintlayout.widget.ConstraintSet.TOP +import com.android.systemui.R +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags +import com.android.systemui.keyguard.shared.model.KeyguardSection +import com.android.systemui.shade.NotificationPanelView +import com.android.systemui.statusbar.phone.NotificationIconAreaController +import com.android.systemui.statusbar.phone.NotificationIconContainer +import javax.inject.Inject + +class AodNotificationIconsSection +@Inject +constructor( + private val context: Context, + private val featureFlags: FeatureFlags, + private val notificationPanelView: NotificationPanelView, + private val notificationIconAreaController: NotificationIconAreaController, +) : KeyguardSection() { + private val nicId = R.id.aod_notification_icon_container + private lateinit var nic: NotificationIconContainer + + override fun addViews(constraintLayout: ConstraintLayout) { + if (!featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) { + return + } + nic = + NotificationIconContainer(context, null).apply { + id = nicId + setPaddingRelative( + resources.getDimensionPixelSize(R.dimen.below_clock_padding_start_icons), + 0, + 0, + 0 + ) + setVisibility(View.INVISIBLE) + } + + constraintLayout.addView(nic) + } + + override fun bindData(constraintLayout: ConstraintLayout) { + if (!featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) { + return + } + + notificationIconAreaController.setupAodIcons(nic) + } + + override fun applyConstraints(constraintSet: ConstraintSet) { + if (!featureFlags.isEnabled(Flags.MIGRATE_KEYGUARD_STATUS_VIEW)) { + return + } + val bottomMargin = + context.resources.getDimensionPixelSize(R.dimen.keyguard_status_view_bottom_margin) + + val useSplitShade = context.resources.getBoolean(R.bool.config_use_split_notification_shade) + + val topAlignment = + if (useSplitShade) { + TOP + } else { + BOTTOM + } + + constraintSet.apply { + connect(nicId, TOP, R.id.keyguard_status_view, topAlignment, bottomMargin) + connect(nicId, START, PARENT_ID, START) + connect(nicId, END, PARENT_ID, END) + constrainHeight( + nicId, + context.resources.getDimensionPixelSize(R.dimen.notification_shelf_height) + ) + } + } + + override fun removeViews(constraintLayout: ConstraintLayout) { + constraintLayout.removeView(nicId) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt index 3e91d9336b13..9c6e953ad2d5 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultLockIconSection.kt @@ -54,15 +54,15 @@ constructor( if (!featureFlags.isEnabled(Flags.MIGRATE_LOCK_ICON)) { return } - notificationPanelView.findViewById<View>(R.id.lock_icon_view).let { + notificationPanelView.findViewById<View>(lockIconViewId).let { notificationPanelView.removeView(it) } - val view = LockIconView(context, null).apply { id = R.id.lock_icon_view } + val view = LockIconView(context, null).apply { id = lockIconViewId } constraintLayout.addView(view) } override fun bindData(constraintLayout: ConstraintLayout) { - constraintLayout.findViewById<LockIconView?>(R.id.lock_icon_view)?.let { + constraintLayout.findViewById<LockIconView?>(lockIconViewId)?.let { lockIconViewController.setLockIconView(it) } } @@ -97,7 +97,7 @@ constructor( } override fun removeViews(constraintLayout: ConstraintLayout) { - constraintLayout.removeView(R.id.lock_icon_view) + constraintLayout.removeView(lockIconViewId) } @VisibleForTesting diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt index 59c5d78bfce8..7fff43b82e93 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultNotificationStackScrollLayoutSection.kt @@ -17,10 +17,16 @@ package com.android.systemui.keyguard.ui.view.layout.sections +import android.content.Context import android.view.View import android.view.ViewGroup import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet +import androidx.constraintlayout.widget.ConstraintSet.BOTTOM +import androidx.constraintlayout.widget.ConstraintSet.END +import androidx.constraintlayout.widget.ConstraintSet.PARENT_ID +import androidx.constraintlayout.widget.ConstraintSet.START +import androidx.constraintlayout.widget.ConstraintSet.TOP import com.android.systemui.R import com.android.systemui.flags.FeatureFlags import com.android.systemui.flags.Flags @@ -35,12 +41,15 @@ import javax.inject.Inject class DefaultNotificationStackScrollLayoutSection @Inject constructor( + private val context: Context, private val featureFlags: FeatureFlags, private val notificationPanelView: NotificationPanelView, private val sharedNotificationContainer: SharedNotificationContainer, private val sharedNotificationContainerViewModel: SharedNotificationContainerViewModel, private val controller: NotificationStackScrollLayoutController, ) : KeyguardSection() { + private val placeHolderId = R.id.nssl_placeholder + override fun addViews(constraintLayout: ConstraintLayout) { if (!featureFlags.isEnabled(Flags.MIGRATE_NSSL)) { return @@ -51,19 +60,52 @@ constructor( (it.parent as ViewGroup).removeView(it) sharedNotificationContainer.addNotificationStackScrollLayout(it) } + + val view = View(context, null).apply { id = placeHolderId } + constraintLayout.addView(view) } override fun bindData(constraintLayout: ConstraintLayout) { - if (featureFlags.isEnabled(Flags.MIGRATE_NSSL)) { - SharedNotificationContainerBinder.bind( - sharedNotificationContainer, - sharedNotificationContainerViewModel, - controller, - ) + if (!featureFlags.isEnabled(Flags.MIGRATE_NSSL)) { + return } + SharedNotificationContainerBinder.bind( + sharedNotificationContainer, + sharedNotificationContainerViewModel, + controller, + ) } - override fun applyConstraints(constraintSet: ConstraintSet) {} + override fun applyConstraints(constraintSet: ConstraintSet) { + if (!featureFlags.isEnabled(Flags.MIGRATE_NSSL)) { + return + } + constraintSet.apply { + val bottomMargin = + context.resources.getDimensionPixelSize(R.dimen.keyguard_status_view_bottom_margin) + val useSplitShade = + context.resources.getBoolean(R.bool.config_use_split_notification_shade) + + val topAlignment = + if (useSplitShade) { + TOP + } else { + BOTTOM + } + connect( + R.id.nssl_placeholder, + TOP, + R.id.keyguard_status_view, + topAlignment, + bottomMargin + ) + connect(R.id.nssl_placeholder, START, PARENT_ID, START) + connect(R.id.nssl_placeholder, END, PARENT_ID, END) + connect(R.id.nssl_placeholder, BOTTOM, R.id.lock_icon_view, TOP) + } + } - override fun removeViews(constraintLayout: ConstraintLayout) {} + override fun removeViews(constraintLayout: ConstraintLayout) { + constraintLayout.removeView(placeHolderId) + } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt index b144f7ae6906..b1dd373a7657 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/view/layout/sections/DefaultStatusViewSection.kt @@ -72,6 +72,11 @@ constructor( .inflate(R.layout.keyguard_status_view, constraintLayout, false) as KeyguardStatusView) .apply { clipChildren = false } + + // This is diassembled and moved to [AodNotificationIconsSection] + keyguardStatusView.findViewById<View>(R.id.left_aligned_notification_icon_container)?.let { + it.setVisibility(View.GONE) + } constraintLayout.addView(keyguardStatusView) } diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java index 4a76dd0df47b..2dbcbc9e0f22 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java @@ -40,6 +40,7 @@ import android.view.IWindow; import android.view.IWindowSession; import android.view.View; import android.view.ViewGroup; +import android.view.WindowInsets; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.WindowManagerGlobal; @@ -409,9 +410,9 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW private void applyForceShowNavigationFlag(NotificationShadeWindowState state) { if (state.panelExpanded || state.bouncerShowing || ENABLE_REMOTE_INPUT && state.remoteInputActive) { - mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; + mLpChanged.forciblyShownTypes |= WindowInsets.Type.navigationBars(); } else { - mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; + mLpChanged.forciblyShownTypes &= ~WindowInsets.Type.navigationBars(); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java index ac8001058ef6..d5e4902366e7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/RemoteInputController.java @@ -102,18 +102,21 @@ public class RemoteInputController { mLogger.logRemoveRemoteInput( entry.getKey() /* entryKey*/, true /* remoteEditImeVisible */, - true /* remoteEditImeAnimatingAway */); + true /* remoteEditImeAnimatingAway */, + isRemoteInputActive(entry) /* isRemoteInputActiveForEntry */, + isRemoteInputActive() /* isRemoteInputActive */); return; } // If the view is being removed, this may be called even though we're not active - boolean remoteInputActive = isRemoteInputActive(entry); + boolean remoteInputActiveForEntry = isRemoteInputActive(entry); mLogger.logRemoveRemoteInput( - entry.getKey() /* entryKey*/, + entry.getKey() /* entryKey */, entry.mRemoteEditImeVisible /* remoteEditImeVisible */, entry.mRemoteEditImeAnimatingAway /* remoteEditImeAnimatingAway */, - remoteInputActive /* isRemoteInputActive */); + remoteInputActiveForEntry /* isRemoteInputActiveForEntry */, + isRemoteInputActive()/* isRemoteInputActive */); - if (!remoteInputActive) return; + if (!remoteInputActiveForEntry) return; pruneWeakThenRemoveAndContains(null /* contains */, entry /* remove */, token); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RemoteInputControllerLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/RemoteInputControllerLogger.kt index 7809eaafe0b3..39b999cb4f35 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/RemoteInputControllerLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/RemoteInputControllerLogger.kt @@ -51,7 +51,8 @@ constructor(@NotificationRemoteInputLog private val logBuffer: LogBuffer) { entryKey: String, remoteEditImeVisible: Boolean, remoteEditImeAnimatingAway: Boolean, - isRemoteInputActive: Boolean? = null + isRemoteInputActiveForEntry: Boolean, + isRemoteInputActive: Boolean ) = logBuffer.log( TAG, @@ -60,11 +61,13 @@ constructor(@NotificationRemoteInputLog private val logBuffer: LogBuffer) { str1 = entryKey bool1 = remoteEditImeVisible bool2 = remoteEditImeAnimatingAway - str2 = isRemoteInputActive?.toString() ?: "N/A" + bool3 = isRemoteInputActiveForEntry + bool4 = isRemoteInputActive }, { "removeRemoteInput entry: $str1, remoteEditImeVisible: $bool1" + - ", remoteEditImeAnimatingAway: $bool2, isActive: $str2" + ", remoteEditImeAnimatingAway: $bool2, isRemoteInputActiveForEntry: $bool3" + + ", isRemoteInputActive: $bool4" } ) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index b797c6339a34..b45a688e6760 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -2680,6 +2680,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { && mStatusBarStateController.getDozeAmount() == 1f && mWakefulnessLifecycle.getLastWakeReason() == PowerManager.WAKE_REASON_POWER_BUTTON + && mFingerprintManager.get() != null && mFingerprintManager.get().isPowerbuttonFps() && mKeyguardUpdateMonitor .getCachedIsUnlockWithFingerprintPossible( diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogFactory.kt index 3b150656efc5..d91ca92747f3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogFactory.kt @@ -48,13 +48,14 @@ constructor( */ fun create( context: Context = this.applicationContext, + theme: Int = SystemUIDialog.DEFAULT_THEME, dismissOnDeviceLock: Boolean = SystemUIDialog.DEFAULT_DISMISS_ON_DEVICE_LOCK, ): ComponentSystemUIDialog { Assert.isMainThread() return ComponentSystemUIDialog( context, - SystemUIDialog.DEFAULT_THEME, + theme, dismissOnDeviceLock, featureFlags, dialogManager, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java index 24987abd7a85..f4cc0ed30781 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java @@ -21,7 +21,6 @@ import static android.view.WindowInsets.Type.statusBars; import static android.view.WindowInsets.Type.tappableElement; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE; import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE; @@ -44,6 +43,7 @@ import android.view.InsetsFrameProvider; import android.view.Surface; import android.view.View; import android.view.ViewGroup; +import android.view.WindowInsets; import android.view.WindowManager; import com.android.internal.policy.SystemBarUtils; @@ -361,9 +361,9 @@ public class StatusBarWindowController { || state.mIsLaunchAnimationRunning // Don't force-show the status bar if the user has already dismissed it. || state.mOngoingProcessRequiresStatusBarVisible) { - mLpChanged.privateFlags |= PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; + mLpChanged.forciblyShownTypes |= WindowInsets.Type.statusBars(); } else { - mLpChanged.privateFlags &= ~PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; + mLpChanged.forciblyShownTypes &= ~WindowInsets.Type.statusBars(); } } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java index 1be87463250f..3d8719656a1e 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerBaseTest.java @@ -20,6 +20,7 @@ import static android.view.View.INVISIBLE; import static com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR; import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; +import static com.android.systemui.flags.Flags.MIGRATE_KEYGUARD_STATUS_VIEW; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.atLeast; @@ -165,6 +166,7 @@ public class KeyguardClockSwitchControllerBaseTest extends SysuiTestCase { mFakeFeatureFlags = new FakeFeatureFlags(); mFakeFeatureFlags.set(FACE_AUTH_REFACTOR, false); mFakeFeatureFlags.set(LOCKSCREEN_WALLPAPER_DREAM_ENABLED, false); + mFakeFeatureFlags.set(MIGRATE_KEYGUARD_STATUS_VIEW, false); mController = new KeyguardClockSwitchController( mView, mStatusBarStateController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt index 41ba1f422d92..681fce822342 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/blueprints/DefaultKeyguardBlueprintTest.kt @@ -28,6 +28,7 @@ import com.android.systemui.flags.Flags import com.android.systemui.keyguard.shared.model.KeyguardBlueprint import com.android.systemui.keyguard.shared.model.KeyguardSection import com.android.systemui.keyguard.ui.view.KeyguardRootView +import com.android.systemui.keyguard.ui.view.layout.sections.AodNotificationIconsSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultAmbientIndicationAreaSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultIndicationAreaSection import com.android.systemui.keyguard.ui.view.layout.sections.DefaultLockIconSection @@ -61,6 +62,8 @@ class DefaultKeyguardBlueprintTest : SysuiTestCase() { @Mock private lateinit var defaultStatusViewSection: DefaultStatusViewSection @Mock private lateinit var defaultNSSLSection: DefaultNotificationStackScrollLayoutSection @Mock private lateinit var splitShadeGuidelines: SplitShadeGuidelines + @Mock private lateinit var aodNotificationIconsSection: AodNotificationIconsSection + private val featureFlags = FakeFeatureFlags() @Before @@ -77,6 +80,7 @@ class DefaultKeyguardBlueprintTest : SysuiTestCase() { defaultStatusViewSection, defaultNSSLSection, splitShadeGuidelines, + aodNotificationIconsSection, featureFlags, ) featureFlags.set(Flags.LAZY_INFLATE_KEYGUARD, false) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index 137566bf1a2a..bd3fb9f1cae3 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -399,7 +399,6 @@ public class CentralSurfacesImplTest extends SysuiTestCase { when(mGradientColors.supportsDarkText()).thenReturn(true); when(mColorExtractor.getNeutralColors()).thenReturn(mGradientColors); - ConfigurationController configurationController = new ConfigurationControllerImpl(mContext); when(mLockscreenWallpaperLazy.get()).thenReturn(mLockscreenWallpaper); when(mBiometricUnlockControllerLazy.get()).thenReturn(mBiometricUnlockController); @@ -438,6 +437,11 @@ public class CentralSurfacesImplTest extends SysuiTestCase { when(mUserTracker.getUserHandle()).thenReturn( UserHandle.of(ActivityManager.getCurrentUser())); + createCentralSurfaces(); + } + + private void createCentralSurfaces() { + ConfigurationController configurationController = new ConfigurationControllerImpl(mContext); mCentralSurfaces = new CentralSurfacesImpl( mContext, mNotificationsController, @@ -1083,6 +1087,27 @@ public class CentralSurfacesImplTest extends SysuiTestCase { verify(mNotificationPanelViewController).setTouchAndAnimationDisabled(true); } + /** Regression test for b/298355063 */ + @Test + public void fingerprintManagerNull_noNPE() { + // GIVEN null fingerprint manager + mFingerprintManager = null; + createCentralSurfaces(); + + // GIVEN should animate doze wakeup + when(mDozeServiceHost.shouldAnimateWakeup()).thenReturn(true); + when(mBiometricUnlockController.getMode()).thenReturn( + BiometricUnlockController.MODE_ONLY_WAKE); + when(mDozeServiceHost.isPulsing()).thenReturn(false); + when(mStatusBarStateController.getDozeAmount()).thenReturn(1f); + + // WHEN waking up from the power button + mWakefulnessLifecycle.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON); + mCentralSurfaces.mWakefulnessObserver.onStartedWakingUp(); + + // THEN no NPE when fingerprintManager is null + } + /** * Configures the appropriate mocks and then calls {@link CentralSurfacesImpl#updateIsKeyguard} * to reconfigure the keyguard to reflect the requested showing/occluded states. diff --git a/services/accessibility/Android.bp b/services/accessibility/Android.bp index bf8a9af99076..e9bb763e143a 100644 --- a/services/accessibility/Android.bp +++ b/services/accessibility/Android.bp @@ -27,4 +27,20 @@ java_library_static { "services.core", "androidx.annotation_annotation", ], + static_libs: [ + "com_android_server_accessibility_flags_lib", + ], +} + +aconfig_declarations { + name: "com_android_server_accessibility_flags", + package: "com.android.server.accessibility", + srcs: [ + "accessibility.aconfig", + ], +} + +java_aconfig_library { + name: "com_android_server_accessibility_flags_lib", + aconfig_declarations: "com_android_server_accessibility_flags", } diff --git a/services/accessibility/accessibility.aconfig b/services/accessibility/accessibility.aconfig new file mode 100644 index 000000000000..b5fc2b6be22d --- /dev/null +++ b/services/accessibility/accessibility.aconfig @@ -0,0 +1,7 @@ +package: "com.android.server.accessibility" +flag { + name: "proxy_use_apps_on_virtual_device_listener" + namespace: "accessibility" + description: "Fixes race condition described in b/286587811" + bug: "286587811" +} diff --git a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java index 119f575011d8..ed77476a2295 100644 --- a/services/accessibility/java/com/android/server/accessibility/ProxyManager.java +++ b/services/accessibility/java/com/android/server/accessibility/ProxyManager.java @@ -33,6 +33,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.util.ArraySet; import android.util.IntArray; import android.util.Slog; import android.util.SparseArray; @@ -42,6 +43,7 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IAccessibilityManagerClient; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.IntPair; import com.android.server.LocalServices; import com.android.server.companion.virtual.VirtualDeviceManagerInternal; @@ -96,6 +98,9 @@ public class ProxyManager { private final SystemSupport mSystemSupport; + private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener + mAppsOnVirtualDeviceListener; + /** * Callbacks into AccessibilityManagerService. */ @@ -174,6 +179,16 @@ public class ProxyManager { synchronized (mLock) { mProxyA11yServiceConnections.put(displayId, connection); + if (Flags.proxyUseAppsOnVirtualDeviceListener()) { + if (mAppsOnVirtualDeviceListener == null) { + mAppsOnVirtualDeviceListener = allRunningUids -> + notifyProxyOfRunningAppsChange(allRunningUids); + final VirtualDeviceManagerInternal localVdm = getLocalVdm(); + if (localVdm != null) { + localVdm.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener); + } + } + } } // If the client dies, make sure to remove the connection. @@ -276,11 +291,21 @@ public class ProxyManager { } } }); - // If there isn't an existing proxy for the device id, reset clients. Resetting + // If there isn't an existing proxy for the device id, reset app clients. Resetting // will usually happen, since in most cases there will only be one proxy for a // device. if (!isProxyedDeviceId(deviceId)) { synchronized (mLock) { + if (Flags.proxyUseAppsOnVirtualDeviceListener()) { + if (mProxyA11yServiceConnections.size() == 0) { + final VirtualDeviceManagerInternal localVdm = getLocalVdm(); + if (localVdm != null && mAppsOnVirtualDeviceListener != null) { + localVdm.unregisterAppsOnVirtualDeviceListener( + mAppsOnVirtualDeviceListener); + mAppsOnVirtualDeviceListener = null; + } + } + } mSystemSupport.removeDeviceIdLocked(deviceId); mLastStates.delete(deviceId); } @@ -307,7 +332,7 @@ public class ProxyManager { * Returns {@code true} if {@code deviceId} is being proxy-ed. */ public boolean isProxyedDeviceId(int deviceId) { - if (deviceId == DEVICE_ID_DEFAULT && deviceId == DEVICE_ID_INVALID) { + if (deviceId == DEVICE_ID_DEFAULT || deviceId == DEVICE_ID_INVALID) { return false; } boolean isTrackingDeviceId; @@ -566,7 +591,7 @@ public class ProxyManager { * This is similar to onUserStateChangeLocked and onClientChangeLocked, but does not require an * A11yUserState and only checks proxy-relevant settings. */ - public void onProxyChanged(int deviceId) { + private void onProxyChanged(int deviceId, boolean forceUpdate) { if (DEBUG) { Slog.v(LOG_TAG, "onProxyChanged called for deviceId: " + deviceId); } @@ -584,7 +609,7 @@ public class ProxyManager { // Calls A11yManager#setRelevantEventTypes (test these) updateRelevantEventTypesLocked(deviceId); // Calls A11yManager#setState - scheduleUpdateProxyClientsIfNeededLocked(deviceId); + scheduleUpdateProxyClientsIfNeededLocked(deviceId, forceUpdate); //Calls A11yManager#notifyServicesStateChanged(timeout) scheduleNotifyProxyClientsOfServicesStateChangeLocked(deviceId); // Calls A11yManager#setFocusAppearance @@ -594,16 +619,25 @@ public class ProxyManager { } /** + * Handles proxy changes, but does not force an update of app clients. + */ + public void onProxyChanged(int deviceId) { + onProxyChanged(deviceId, false); + } + + /** * Updates the states of the app AccessibilityManagers. */ - private void scheduleUpdateProxyClientsIfNeededLocked(int deviceId) { + private void scheduleUpdateProxyClientsIfNeededLocked(int deviceId, boolean forceUpdate) { final int proxyState = getStateLocked(deviceId); if (DEBUG) { Slog.v(LOG_TAG, "State for device id " + deviceId + " is " + proxyState); Slog.v(LOG_TAG, "Last state for device id " + deviceId + " is " + getLastSentStateLocked(deviceId)); + Slog.v(LOG_TAG, "force update: " + forceUpdate); } - if ((getLastSentStateLocked(deviceId)) != proxyState) { + if ((getLastSentStateLocked(deviceId)) != proxyState + || (Flags.proxyUseAppsOnVirtualDeviceListener() && forceUpdate)) { setLastStateLocked(deviceId, proxyState); mMainHandler.post(() -> { synchronized (mLock) { @@ -792,7 +826,7 @@ public class ProxyManager { } /** - * Updates the device ids of IAccessibilityManagerClients if needed. + * Updates the device ids of IAccessibilityManagerClients if needed after a proxy change. */ private void updateDeviceIdsIfNeededLocked(int deviceId, @NonNull RemoteCallbackList<IAccessibilityManagerClient> clients) { @@ -804,13 +838,66 @@ public class ProxyManager { for (int i = 0; i < clients.getRegisteredCallbackCount(); i++) { final AccessibilityManagerService.Client client = ((AccessibilityManagerService.Client) clients.getRegisteredCallbackCookie(i)); - if (deviceId != DEVICE_ID_DEFAULT && deviceId != DEVICE_ID_INVALID + if (Flags.proxyUseAppsOnVirtualDeviceListener()) { + if (deviceId == DEVICE_ID_DEFAULT || deviceId == DEVICE_ID_INVALID) { + continue; + } + boolean uidBelongsToDevice = + localVdm.getDeviceIdsForUid(client.mUid).contains(deviceId); + if (client.mDeviceId != deviceId && uidBelongsToDevice) { + if (DEBUG) { + Slog.v(LOG_TAG, "Packages moved to device id " + deviceId + " are " + + Arrays.toString(client.mPackageNames)); + } + client.mDeviceId = deviceId; + } else if (client.mDeviceId == deviceId && !uidBelongsToDevice) { + client.mDeviceId = DEVICE_ID_DEFAULT; + if (DEBUG) { + Slog.v(LOG_TAG, "Packages moved to the default device from device id " + + deviceId + " are " + Arrays.toString(client.mPackageNames)); + } + } + } else { + if (deviceId != DEVICE_ID_DEFAULT && deviceId != DEVICE_ID_INVALID && localVdm.getDeviceIdsForUid(client.mUid).contains(deviceId)) { - if (DEBUG) { - Slog.v(LOG_TAG, "Packages moved to device id " + deviceId + " are " - + Arrays.toString(client.mPackageNames)); + if (DEBUG) { + Slog.v(LOG_TAG, "Packages moved to device id " + deviceId + " are " + + Arrays.toString(client.mPackageNames)); + } + client.mDeviceId = deviceId; } - client.mDeviceId = deviceId; + } + } + } + + @VisibleForTesting + void notifyProxyOfRunningAppsChange(Set<Integer> allRunningUids) { + if (DEBUG) { + Slog.v(LOG_TAG, "notifyProxyOfRunningAppsChange: " + allRunningUids); + } + synchronized (mLock) { + if (mProxyA11yServiceConnections.size() == 0) { + return; + } + final VirtualDeviceManagerInternal localVdm = getLocalVdm(); + if (localVdm == null) { + return; + } + final ArraySet<Integer> deviceIdsToUpdate = new ArraySet<>(); + for (int i = 0; i < mProxyA11yServiceConnections.size(); i++) { + final ProxyAccessibilityServiceConnection proxy = + mProxyA11yServiceConnections.valueAt(i); + if (proxy != null) { + final int proxyDeviceId = proxy.getDeviceId(); + for (Integer uid : allRunningUids) { + if (localVdm.getDeviceIdsForUid(uid).contains(proxyDeviceId)) { + deviceIdsToUpdate.add(proxyDeviceId); + } + } + } + } + for (Integer proxyDeviceId : deviceIdsToUpdate) { + onProxyChanged(proxyDeviceId, true); } } } @@ -843,6 +930,11 @@ public class ProxyManager { return mLocalVdm; } + @VisibleForTesting + void setLocalVirtualDeviceManager(VirtualDeviceManagerInternal localVdm) { + mLocalVdm = localVdm; + } + /** * Prints information belonging to each display that is controlled by an * AccessibilityDisplayProxy. diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java index 39756dfee7bf..cae047ff0624 100644 --- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java +++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceShellCommand.java @@ -18,7 +18,6 @@ package com.android.server.autofill; import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES; import static android.service.autofill.AutofillService.EXTRA_RESULT; - import static com.android.server.autofill.AutofillManagerService.RECEIVER_BUNDLE_EXTRA_SESSIONS; import android.os.Bundle; @@ -155,20 +154,31 @@ public final class AutofillManagerServiceShellCommand extends ShellCommand { pw.println(""); } + Method[] flagMethods = {}; + try { - Method[] flagMethods = Flags.class.getMethods(); - // For some reason, unreferenced flags do not show up here - // Maybe compiler optomized them out of bytecode? - for (Method method : flagMethods) { - if (Modifier.isPublic(method.getModifiers())) { - pw.println(method.getName() + ": " + method.invoke(null)); - } - } - } catch (Exception ex) { - pw.println(ex); + flagMethods = Flags.class.getDeclaredMethods(); + } catch (SecurityException ex) { + ex.printStackTrace(pw); return -1; } + // For some reason, unreferenced flags do not show up here + // Maybe compiler optomized them out of bytecode? + for (Method method : flagMethods) { + if (!Modifier.isPublic(method.getModifiers())) { + continue; + } + try { + pw.print(method.getName() + ": "); + pw.print(method.invoke(null)); + } catch (Exception ex) { + ex.printStackTrace(pw); + } finally { + pw.println(""); + } + } + return 0; } diff --git a/services/core/Android.bp b/services/core/Android.bp index 7329f1afb275..b941aaf32853 100644 --- a/services/core/Android.bp +++ b/services/core/Android.bp @@ -180,7 +180,6 @@ java_library_static { "android.hardware.rebootescrow-V1-java", "android.hardware.power.stats-V2-java", "android.hidl.manager-V1.2-java", - "com.android.server.security.flags-aconfig-java", "cbor-java", "display_flags_lib", "icu4j_calendar_astronomer", diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 0d265a0f4c4a..b5911f69b156 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -9543,6 +9543,14 @@ public class ActivityManagerService extends IActivityManager.Stub } } else { worker.start(); + if (process != null && process.mPid == MY_PID && "crash".equals(eventType)) { + // We're actually crashing, let's wait for up to 2 seconds before killing ourselves, + // so the data could be persisted into the dropbox. + try { + worker.join(2000); + } catch (InterruptedException ignored) { + } + } } } diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java index d3176ee46464..87077a677758 100644 --- a/services/core/java/com/android/server/am/OomAdjuster.java +++ b/services/core/java/com/android/server/am/OomAdjuster.java @@ -2823,9 +2823,7 @@ public class OomAdjuster { } } - if (schedGroup < SCHED_GROUP_TOP_APP - && cr.hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP) - && clientIsSystem) { + if (cr.hasFlag(Context.BIND_SCHEDULE_LIKE_TOP_APP) && clientIsSystem) { schedGroup = SCHED_GROUP_TOP_APP; state.setScheduleLikeTopApp(true); } diff --git a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java index fdf607d04ec7..64691e0b062b 100644 --- a/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java +++ b/services/core/java/com/android/server/biometrics/AuthenticationStatsCollector.java @@ -53,6 +53,9 @@ public class AuthenticationStatsCollector { static final int MAXIMUM_ENROLLMENT_NOTIFICATIONS = 1; @NonNull private final Context mContext; + @NonNull private final PackageManager mPackageManager; + @NonNull private final FaceManager mFaceManager; + @NonNull private final FingerprintManager mFingerprintManager; private final float mThreshold; private final int mModality; @@ -86,6 +89,10 @@ public class AuthenticationStatsCollector { mModality = modality; mBiometricNotification = biometricNotification; + mPackageManager = context.getPackageManager(); + mFaceManager = mContext.getSystemService(FaceManager.class); + mFingerprintManager = mContext.getSystemService(FingerprintManager.class); + IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(Intent.ACTION_USER_REMOVED); context.registerReceiver(mBroadcastReceiver, intentFilter); @@ -108,6 +115,13 @@ public class AuthenticationStatsCollector { /** Update total authentication and rejected attempts. */ public void authenticate(int userId, boolean authenticated) { + + // Don't collect data for single-modality devices or user has both biometrics enrolled. + if (isSingleModalityDevice() + || (hasEnrolledFace(userId) && hasEnrolledFingerprint(userId))) { + return; + } + // SharedPreference is not ready when starting system server, initialize // mUserAuthenticationStatsMap in authentication to ensure SharedPreference // is ready for application use. @@ -150,25 +164,9 @@ public class AuthenticationStatsCollector { authenticationStats.resetData(); - final PackageManager packageManager = mContext.getPackageManager(); - - // Don't send notification to single-modality devices. - if (!packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT) - || !packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) { - return; - } - - final FaceManager faceManager = mContext.getSystemService(FaceManager.class); - final boolean hasEnrolledFace = faceManager.hasEnrolledTemplates(userId); + final boolean hasEnrolledFace = hasEnrolledFace(userId); + final boolean hasEnrolledFingerprint = hasEnrolledFingerprint(userId); - final FingerprintManager fingerprintManager = mContext - .getSystemService(FingerprintManager.class); - final boolean hasEnrolledFingerprint = fingerprintManager.hasEnrolledTemplates(userId); - - // Don't send notification when both face and fingerprint are enrolled. - if (hasEnrolledFace && hasEnrolledFingerprint) { - return; - } if (hasEnrolledFace && !hasEnrolledFingerprint) { mBiometricNotification.sendFpEnrollNotification(mContext); authenticationStats.updateNotificationCounter(); @@ -199,6 +197,19 @@ public class AuthenticationStatsCollector { } } + private boolean isSingleModalityDevice() { + return !mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT) + || !mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE); + } + + private boolean hasEnrolledFace(int userId) { + return mFaceManager.hasEnrolledTemplates(userId); + } + + private boolean hasEnrolledFingerprint(int userId) { + return mFingerprintManager.hasEnrolledTemplates(userId); + } + /** * Only being used in tests. Callers should not make any changes to the returned * authentication stats. diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java index f1c74f0b9fb2..2aec9aefa8d1 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricNotificationUtils.java @@ -176,6 +176,7 @@ public class BiometricNotificationUtils { .setSmallIcon(R.drawable.ic_lock) .setContentTitle(title) .setContentText(content) + .setStyle(new Notification.BigTextStyle().bigText(content)) .setSubText(name) .setOnlyAlertOnce(true) .setLocalOnly(true) diff --git a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java index adea13fcc13c..d4232ab60eec 100644 --- a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java +++ b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java @@ -29,7 +29,6 @@ import android.hardware.broadcastradio.Metadata; import android.hardware.broadcastradio.ProgramFilter; import android.hardware.broadcastradio.ProgramIdentifier; import android.hardware.broadcastradio.ProgramInfo; -import android.hardware.broadcastradio.ProgramListChunk; import android.hardware.broadcastradio.Properties; import android.hardware.broadcastradio.Result; import android.hardware.broadcastradio.VendorKeyValue; @@ -38,6 +37,7 @@ import android.hardware.radio.ProgramSelector; import android.hardware.radio.RadioManager; import android.hardware.radio.RadioMetadata; import android.hardware.radio.RadioTuner; +import android.hardware.radio.UniqueProgramIdentifier; import android.os.Build; import android.os.ParcelableException; import android.os.ServiceSpecificException; @@ -553,31 +553,6 @@ final class ConversionUtils { return hwFilter; } - static ProgramList.Chunk chunkFromHalProgramListChunk(ProgramListChunk chunk) { - Set<RadioManager.ProgramInfo> modified = new ArraySet<>(chunk.modified.length); - for (int i = 0; i < chunk.modified.length; i++) { - RadioManager.ProgramInfo modifiedInfo = - programInfoFromHalProgramInfo(chunk.modified[i]); - if (modifiedInfo == null) { - Slogf.w(TAG, "Program info %s in program list chunk is not valid", - chunk.modified[i]); - continue; - } - modified.add(modifiedInfo); - } - Set<ProgramSelector.Identifier> removed = new ArraySet<>(); - if (chunk.removed != null) { - for (int i = 0; i < chunk.removed.length; i++) { - ProgramSelector.Identifier removedId = - identifierFromHalProgramIdentifier(chunk.removed[i]); - if (removedId != null) { - removed.add(removedId); - } - } - } - return new ProgramList.Chunk(chunk.purge, chunk.complete, modified, removed); - } - private static boolean isNewIdentifierInU(ProgramSelector.Identifier id) { return id.getType() == ProgramSelector.IDENTIFIER_TYPE_DAB_DMB_SID_EXT; } @@ -630,11 +605,11 @@ final class ConversionUtils { modified.add(info); } } - Set<ProgramSelector.Identifier> removed = new ArraySet<>(); - Iterator<ProgramSelector.Identifier> removedIterator = chunk.getRemoved().iterator(); + Set<UniqueProgramIdentifier> removed = new ArraySet<>(); + Iterator<UniqueProgramIdentifier> removedIterator = chunk.getRemoved().iterator(); while (removedIterator.hasNext()) { - ProgramSelector.Identifier id = removedIterator.next(); - if (!isNewIdentifierInU(id)) { + UniqueProgramIdentifier id = removedIterator.next(); + if (!isNewIdentifierInU(id.getPrimaryId())) { removed.add(id); } } diff --git a/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java b/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java index c9ae735d63e2..756dbbbc612b 100644 --- a/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java +++ b/services/core/java/com/android/server/broadcastradio/aidl/ProgramInfoCache.java @@ -17,9 +17,11 @@ package com.android.server.broadcastradio.aidl; import android.annotation.Nullable; +import android.hardware.broadcastradio.ProgramListChunk; import android.hardware.radio.ProgramList; -import android.hardware.radio.ProgramSelector; +import android.hardware.radio.ProgramSelector.Identifier; import android.hardware.radio.RadioManager; +import android.hardware.radio.UniqueProgramIdentifier; import android.util.ArrayMap; import android.util.ArraySet; @@ -30,7 +32,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Set; /** @@ -40,24 +41,25 @@ final class ProgramInfoCache { private static final String TAG = "BcRadioAidlSrv.cache"; /** - * Maximum number of {@link RadioManager#ProgramInfo} elements that will be put into a + * Maximum number of {@link RadioManager.ProgramInfo} elements that will be put into a * ProgramList.Chunk.mModified array. Used to try to ensure a single ProgramList.Chunk * stays within the AIDL data size limit. */ private static final int MAX_NUM_MODIFIED_PER_CHUNK = 100; /** - * Maximum number of {@link ProgramSelector#Identifier} elements that will be put - * into the removed array of {@link ProgramList#Chunk}. Used to try to ensure a single - * {@link ProgramList#Chunk} stays within the AIDL data size limit. + * Maximum number of {@link Identifier} elements that will be put into the removed array + * of {@link ProgramList.Chunk}. Use to attempt and keep the single {@link ProgramList.Chunk} + * within the AIDL data size limit. */ private static final int MAX_NUM_REMOVED_PER_CHUNK = 500; /** - * Map from primary identifier to corresponding {@link RadioManager#ProgramInfo}. + * Map from primary identifier to {@link UniqueProgramIdentifier} and then to corresponding + * {@link RadioManager.ProgramInfo}. */ - private final Map<ProgramSelector.Identifier, RadioManager.ProgramInfo> mProgramInfoMap = - new ArrayMap<>(); + private final ArrayMap<Identifier, ArrayMap<UniqueProgramIdentifier, RadioManager.ProgramInfo>> + mProgramInfoMap = new ArrayMap<>(); /** * Flag indicating whether mProgramInfoMap is considered complete based upon the received @@ -81,13 +83,17 @@ final class ProgramInfoCache { mFilter = filter; mComplete = complete; for (int i = 0; i < programInfos.length; i++) { - mProgramInfoMap.put(programInfos[i].getSelector().getPrimaryId(), programInfos[i]); + putInfo(programInfos[i]); } } @VisibleForTesting List<RadioManager.ProgramInfo> toProgramInfoList() { - return new ArrayList<>(mProgramInfoMap.values()); + List<RadioManager.ProgramInfo> programInfoList = new ArrayList<>(); + for (int index = 0; index < mProgramInfoMap.size(); index++) { + programInfoList.addAll(mProgramInfoMap.valueAt(index).values()); + } + return programInfoList; } @Override @@ -97,10 +103,14 @@ final class ProgramInfoCache { sb.append(", mFilter = "); sb.append(mFilter); sb.append(", mProgramInfoMap = ["); - mProgramInfoMap.forEach((id, programInfo) -> { - sb.append(", "); - sb.append(programInfo); - }); + for (int index = 0; index < mProgramInfoMap.size(); index++) { + ArrayMap<UniqueProgramIdentifier, RadioManager.ProgramInfo> entries = + mProgramInfoMap.valueAt(index); + for (int entryIndex = 0; entryIndex < entries.size(); entryIndex++) { + sb.append(", "); + sb.append(entries.valueAt(entryIndex)); + } + } return sb.append("])").toString(); } @@ -114,8 +124,7 @@ final class ProgramInfoCache { } @VisibleForTesting - void updateFromHalProgramListChunk( - android.hardware.broadcastradio.ProgramListChunk chunk) { + void updateFromHalProgramListChunk(ProgramListChunk chunk) { if (chunk.purge) { mProgramInfoMap.clear(); } @@ -125,8 +134,9 @@ final class ProgramInfoCache { if (programInfo == null) { Slogf.e(TAG, "Program info in program info %s in chunk is not valid", chunk.modified[i]); + continue; } - mProgramInfoMap.put(programInfo.getSelector().getPrimaryId(), programInfo); + putInfo(programInfo); } if (chunk.removed != null) { for (int i = 0; i < chunk.removed.length; i++) { @@ -155,25 +165,31 @@ final class ProgramInfoCache { purge = true; } - Set<RadioManager.ProgramInfo> modified = new ArraySet<>(); - Set<ProgramSelector.Identifier> removed = new ArraySet<>(mProgramInfoMap.keySet()); - for (Map.Entry<ProgramSelector.Identifier, RadioManager.ProgramInfo> entry - : other.mProgramInfoMap.entrySet()) { - ProgramSelector.Identifier id = entry.getKey(); + ArraySet<RadioManager.ProgramInfo> modified = new ArraySet<>(); + ArraySet<UniqueProgramIdentifier> removed = new ArraySet<>(); + for (int index = 0; index < mProgramInfoMap.size(); index++) { + removed.addAll(mProgramInfoMap.valueAt(index).keySet()); + } + for (int index = 0; index < other.mProgramInfoMap.size(); index++) { + Identifier id = other.mProgramInfoMap.keyAt(index); if (!passesFilter(id)) { continue; } - removed.remove(id); + ArrayMap<UniqueProgramIdentifier, RadioManager.ProgramInfo> entries = + other.mProgramInfoMap.valueAt(index); + for (int entryIndex = 0; entryIndex < entries.size(); entryIndex++) { + removed.remove(entries.keyAt(entryIndex)); - RadioManager.ProgramInfo newInfo = entry.getValue(); - if (!shouldIncludeInModified(newInfo)) { - continue; + RadioManager.ProgramInfo newInfo = entries.valueAt(entryIndex); + if (!shouldIncludeInModified(newInfo)) { + continue; + } + putInfo(newInfo); + modified.add(newInfo); } - mProgramInfoMap.put(id, newInfo); - modified.add(newInfo); } - for (ProgramSelector.Identifier rem : removed) { - mProgramInfoMap.remove(rem); + for (int removedIndex = 0; removedIndex < removed.size(); removedIndex++) { + removeUniqueId(removed.valueAt(removedIndex)); } mComplete = other.mComplete; return buildChunks(purge, mComplete, modified, maxNumModifiedPerChunk, removed, @@ -181,45 +197,61 @@ final class ProgramInfoCache { } @Nullable - List<ProgramList.Chunk> filterAndApplyChunk(ProgramList.Chunk chunk) { + List<ProgramList.Chunk> filterAndApplyChunk(ProgramListChunk chunk) { return filterAndApplyChunkInternal(chunk, MAX_NUM_MODIFIED_PER_CHUNK, MAX_NUM_REMOVED_PER_CHUNK); } @VisibleForTesting @Nullable - List<ProgramList.Chunk> filterAndApplyChunkInternal(ProgramList.Chunk chunk, + List<ProgramList.Chunk> filterAndApplyChunkInternal(ProgramListChunk chunk, int maxNumModifiedPerChunk, int maxNumRemovedPerChunk) { - if (chunk.isPurge()) { + if (chunk.purge) { mProgramInfoMap.clear(); } Set<RadioManager.ProgramInfo> modified = new ArraySet<>(); - Set<ProgramSelector.Identifier> removed = new ArraySet<>(); - for (RadioManager.ProgramInfo info : chunk.getModified()) { - ProgramSelector.Identifier id = info.getSelector().getPrimaryId(); - if (!passesFilter(id) || !shouldIncludeInModified(info)) { + for (int i = 0; i < chunk.modified.length; i++) { + RadioManager.ProgramInfo info = + ConversionUtils.programInfoFromHalProgramInfo(chunk.modified[i]); + if (info == null) { + Slogf.w(TAG, "Program info %s in program list chunk is not valid", + chunk.modified[i]); + continue; + } + Identifier primaryId = info.getSelector().getPrimaryId(); + if (!passesFilter(primaryId) || !shouldIncludeInModified(info)) { continue; } - mProgramInfoMap.put(id, info); + putInfo(info); modified.add(info); } - for (ProgramSelector.Identifier id : chunk.getRemoved()) { - if (mProgramInfoMap.containsKey(id)) { - mProgramInfoMap.remove(id); - removed.add(id); + Set<UniqueProgramIdentifier> removed = new ArraySet<>(); + if (chunk.removed != null) { + for (int i = 0; i < chunk.removed.length; i++) { + Identifier removedId = ConversionUtils.identifierFromHalProgramIdentifier( + chunk.removed[i]); + if (removedId == null) { + Slogf.w(TAG, "Removed identifier %s in program list chunk is not valid", + chunk.modified[i]); + continue; + } + if (mProgramInfoMap.containsKey(removedId)) { + removed.addAll(mProgramInfoMap.get(removedId).keySet()); + mProgramInfoMap.remove(removedId); + } } } - if (modified.isEmpty() && removed.isEmpty() && mComplete == chunk.isComplete() - && !chunk.isPurge()) { + if (modified.isEmpty() && removed.isEmpty() && mComplete == chunk.complete + && !chunk.purge) { return null; } - mComplete = chunk.isComplete(); - return buildChunks(chunk.isPurge(), mComplete, modified, maxNumModifiedPerChunk, removed, + mComplete = chunk.complete; + return buildChunks(chunk.purge, mComplete, modified, maxNumModifiedPerChunk, removed, maxNumRemovedPerChunk); } - private boolean passesFilter(ProgramSelector.Identifier id) { + private boolean passesFilter(Identifier id) { if (mFilter == null) { return true; } @@ -233,9 +265,32 @@ final class ProgramInfoCache { return mFilter.areCategoriesIncluded() || !id.isCategoryType(); } + private void putInfo(RadioManager.ProgramInfo info) { + Identifier primaryId = info.getSelector().getPrimaryId(); + if (!mProgramInfoMap.containsKey(primaryId)) { + mProgramInfoMap.put(primaryId, new ArrayMap<>()); + } + mProgramInfoMap.get(primaryId).put(new UniqueProgramIdentifier(info.getSelector()), info); + } + + private void removeUniqueId(UniqueProgramIdentifier uniqueId) { + Identifier primaryId = uniqueId.getPrimaryId(); + if (!mProgramInfoMap.containsKey(primaryId)) { + return; + } + mProgramInfoMap.get(primaryId).remove(uniqueId); + if (mProgramInfoMap.get(primaryId).isEmpty()) { + mProgramInfoMap.remove(primaryId); + } + } + private boolean shouldIncludeInModified(RadioManager.ProgramInfo newInfo) { - RadioManager.ProgramInfo oldInfo = mProgramInfoMap.get( - newInfo.getSelector().getPrimaryId()); + Identifier primaryId = newInfo.getSelector().getPrimaryId(); + RadioManager.ProgramInfo oldInfo = null; + if (mProgramInfoMap.containsKey(primaryId)) { + UniqueProgramIdentifier uniqueId = new UniqueProgramIdentifier(newInfo.getSelector()); + oldInfo = mProgramInfoMap.get(primaryId).get(uniqueId); + } if (oldInfo == null) { return true; } @@ -251,7 +306,7 @@ final class ProgramInfoCache { private static List<ProgramList.Chunk> buildChunks(boolean purge, boolean complete, @Nullable Collection<RadioManager.ProgramInfo> modified, int maxNumModifiedPerChunk, - @Nullable Collection<ProgramSelector.Identifier> removed, int maxNumRemovedPerChunk) { + @Nullable Collection<UniqueProgramIdentifier> removed, int maxNumRemovedPerChunk) { // Communication protocol requires that if purge is set, removed is empty. if (purge) { removed = null; @@ -275,7 +330,7 @@ final class ProgramInfoCache { int modifiedPerChunk = 0; int removedPerChunk = 0; Iterator<RadioManager.ProgramInfo> modifiedIter = null; - Iterator<ProgramSelector.Identifier> removedIter = null; + Iterator<UniqueProgramIdentifier> removedIter = null; if (modified != null) { modifiedPerChunk = roundUpFraction(modified.size(), numChunks); modifiedIter = modified.iterator(); @@ -287,7 +342,7 @@ final class ProgramInfoCache { List<ProgramList.Chunk> chunks = new ArrayList<>(numChunks); for (int i = 0; i < numChunks; i++) { ArraySet<RadioManager.ProgramInfo> modifiedChunk = new ArraySet<>(); - ArraySet<ProgramSelector.Identifier> removedChunk = new ArraySet<>(); + ArraySet<UniqueProgramIdentifier> removedChunk = new ArraySet<>(); if (modifiedIter != null) { for (int j = 0; j < modifiedPerChunk && modifiedIter.hasNext(); j++) { modifiedChunk.add(modifiedIter.next()); diff --git a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java index 7c87c6c55289..2ae7f9543540 100644 --- a/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java +++ b/services/core/java/com/android/server/broadcastradio/aidl/RadioModule.java @@ -142,12 +142,11 @@ final class RadioModule { public void onProgramListUpdated(ProgramListChunk programListChunk) { fireLater(() -> { synchronized (mLock) { - android.hardware.radio.ProgramList.Chunk chunk = - ConversionUtils.chunkFromHalProgramListChunk(programListChunk); - mProgramInfoCache.filterAndApplyChunk(chunk); + mProgramInfoCache.filterAndApplyChunk(programListChunk); for (int i = 0; i < mAidlTunerSessions.size(); i++) { - mAidlTunerSessions.valueAt(i).onMergedProgramListUpdateFromHal(chunk); + mAidlTunerSessions.valueAt(i).onMergedProgramListUpdateFromHal( + programListChunk); } } }); diff --git a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java index beff7bd3cffd..4ed36ec9878c 100644 --- a/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java +++ b/services/core/java/com/android/server/broadcastradio/aidl/TunerSession.java @@ -20,6 +20,7 @@ import android.annotation.Nullable; import android.graphics.Bitmap; import android.hardware.broadcastradio.ConfigFlag; import android.hardware.broadcastradio.IBroadcastRadio; +import android.hardware.broadcastradio.ProgramListChunk; import android.hardware.radio.ITuner; import android.hardware.radio.ProgramList; import android.hardware.radio.ProgramSelector; @@ -297,7 +298,7 @@ final class TunerSession extends ITuner.Stub { } } - void onMergedProgramListUpdateFromHal(ProgramList.Chunk mergedChunk) { + void onMergedProgramListUpdateFromHal(ProgramListChunk mergedChunk) { List<ProgramList.Chunk> clientUpdateChunks; synchronized (mLock) { if (mProgramInfoCache == null) { diff --git a/services/core/java/com/android/server/broadcastradio/hal2/Convert.java b/services/core/java/com/android/server/broadcastradio/hal2/Convert.java index e6908b107d31..fb1138f4bc24 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/Convert.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/Convert.java @@ -28,7 +28,6 @@ import android.hardware.broadcastradio.V2_0.MetadataKey; import android.hardware.broadcastradio.V2_0.ProgramFilter; import android.hardware.broadcastradio.V2_0.ProgramIdentifier; import android.hardware.broadcastradio.V2_0.ProgramInfo; -import android.hardware.broadcastradio.V2_0.ProgramListChunk; import android.hardware.broadcastradio.V2_0.Properties; import android.hardware.broadcastradio.V2_0.Result; import android.hardware.broadcastradio.V2_0.VendorKeyValue; @@ -425,16 +424,6 @@ class Convert { return hwFilter; } - static @NonNull ProgramList.Chunk programListChunkFromHal(@NonNull ProgramListChunk chunk) { - Set<RadioManager.ProgramInfo> modified = chunk.modified.stream(). - map(info -> programInfoFromHal(info)).collect(Collectors.toSet()); - Set<ProgramSelector.Identifier> removed = chunk.removed.stream(). - map(id -> Objects.requireNonNull(programIdentifierFromHal(id))). - collect(Collectors.toSet()); - - return new ProgramList.Chunk(chunk.purge, chunk.complete, modified, removed); - } - public static @NonNull android.hardware.radio.Announcement announcementFromHal( @NonNull Announcement hwAnnouncement) { return new android.hardware.radio.Announcement( diff --git a/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java b/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java index 9831af6b523e..111953d9f6cf 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/ProgramInfoCache.java @@ -16,21 +16,21 @@ package com.android.server.broadcastradio.hal2; -import android.annotation.NonNull; import android.annotation.Nullable; +import android.hardware.broadcastradio.V2_0.ProgramListChunk; import android.hardware.radio.ProgramList; -import android.hardware.radio.ProgramSelector; +import android.hardware.radio.ProgramSelector.Identifier; import android.hardware.radio.RadioManager; +import android.hardware.radio.UniqueProgramIdentifier; +import android.util.ArrayMap; +import android.util.ArraySet; import com.android.internal.annotations.VisibleForTesting; import java.util.ArrayList; import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Set; final class ProgramInfoCache { @@ -40,13 +40,14 @@ final class ProgramInfoCache { private static final int MAX_NUM_MODIFIED_PER_CHUNK = 100; // Maximum number of ProgramSelector.Identifier elements that will be put into a - // ProgramList.Chunk.mRemoved array. Used to try to ensure a single ProgramList.Chunk stays + // ProgramList.Chunk.mRemoved array. Use to attempt and keep the single ProgramList.Chunk // within the AIDL data size limit. private static final int MAX_NUM_REMOVED_PER_CHUNK = 500; - // Map from primary identifier to corresponding ProgramInfo. - private final Map<ProgramSelector.Identifier, RadioManager.ProgramInfo> mProgramInfoMap = - new HashMap<>(); + // Map from primary identifier to a map of unique identifiers and program info, where the + // containing map has unique identifiers to program info. + private final ArrayMap<Identifier, ArrayMap<UniqueProgramIdentifier, RadioManager.ProgramInfo>> + mProgramInfoMap = new ArrayMap<>(); // Flag indicating whether mProgramInfoMap is considered complete based upon the received // updates. @@ -66,18 +67,18 @@ final class ProgramInfoCache { RadioManager.ProgramInfo... programInfos) { mFilter = filter; mComplete = complete; - for (RadioManager.ProgramInfo programInfo : programInfos) { - mProgramInfoMap.put(programInfo.getSelector().getPrimaryId(), programInfo); + for (int i = 0; i < programInfos.length; i++) { + putInfo(programInfos[i]); } } @VisibleForTesting - boolean programInfosAreExactly(RadioManager.ProgramInfo... programInfos) { - Map<ProgramSelector.Identifier, RadioManager.ProgramInfo> expectedMap = new HashMap<>(); - for (RadioManager.ProgramInfo programInfo : programInfos) { - expectedMap.put(programInfo.getSelector().getPrimaryId(), programInfo); + List<RadioManager.ProgramInfo> toProgramInfoList() { + List<RadioManager.ProgramInfo> programInfoList = new ArrayList<>(); + for (int index = 0; index < mProgramInfoMap.size(); index++) { + programInfoList.addAll(mProgramInfoMap.valueAt(index).values()); } - return expectedMap.equals(mProgramInfoMap); + return programInfoList; } @Override @@ -87,10 +88,14 @@ final class ProgramInfoCache { sb.append(", mFilter = "); sb.append(mFilter); sb.append(", mProgramInfoMap = ["); - mProgramInfoMap.forEach((id, programInfo) -> { - sb.append("\n"); - sb.append(programInfo.toString()); - }); + for (int index = 0; index < mProgramInfoMap.size(); index++) { + ArrayMap<UniqueProgramIdentifier, RadioManager.ProgramInfo> entries = + mProgramInfoMap.valueAt(index); + for (int entryIndex = 0; entryIndex < entries.size(); entryIndex++) { + sb.append(", "); + sb.append(entries.valueAt(entryIndex)); + } + } sb.append("]"); return sb.toString(); } @@ -103,14 +108,13 @@ final class ProgramInfoCache { return mFilter; } - void updateFromHalProgramListChunk( - @NonNull android.hardware.broadcastradio.V2_0.ProgramListChunk chunk) { + void updateFromHalProgramListChunk(ProgramListChunk chunk) { if (chunk.purge) { mProgramInfoMap.clear(); } for (android.hardware.broadcastradio.V2_0.ProgramInfo halProgramInfo : chunk.modified) { RadioManager.ProgramInfo programInfo = Convert.programInfoFromHal(halProgramInfo); - mProgramInfoMap.put(programInfo.getSelector().getPrimaryId(), programInfo); + putInfo(programInfo); } for (android.hardware.broadcastradio.V2_0.ProgramIdentifier halProgramId : chunk.removed) { mProgramInfoMap.remove(Convert.programIdentifierFromHal(halProgramId)); @@ -118,14 +122,13 @@ final class ProgramInfoCache { mComplete = chunk.complete; } - @NonNull List<ProgramList.Chunk> filterAndUpdateFrom(@NonNull ProgramInfoCache other, - boolean purge) { + List<ProgramList.Chunk> filterAndUpdateFrom(ProgramInfoCache other, boolean purge) { return filterAndUpdateFromInternal(other, purge, MAX_NUM_MODIFIED_PER_CHUNK, MAX_NUM_REMOVED_PER_CHUNK); } @VisibleForTesting - @NonNull List<ProgramList.Chunk> filterAndUpdateFromInternal(@NonNull ProgramInfoCache other, + List<ProgramList.Chunk> filterAndUpdateFromInternal(ProgramInfoCache other, boolean purge, int maxNumModifiedPerChunk, int maxNumRemovedPerChunk) { if (purge) { mProgramInfoMap.clear(); @@ -136,69 +139,82 @@ final class ProgramInfoCache { purge = true; } - Set<RadioManager.ProgramInfo> modified = new HashSet<>(); - Set<ProgramSelector.Identifier> removed = new HashSet<>(mProgramInfoMap.keySet()); - for (Map.Entry<ProgramSelector.Identifier, RadioManager.ProgramInfo> entry - : other.mProgramInfoMap.entrySet()) { - ProgramSelector.Identifier id = entry.getKey(); + ArraySet<RadioManager.ProgramInfo> modified = new ArraySet<>(); + ArraySet<UniqueProgramIdentifier> removed = new ArraySet<>(); + for (int index = 0; index < mProgramInfoMap.size(); index++) { + removed.addAll(mProgramInfoMap.valueAt(index).keySet()); + } + for (int index = 0; index < other.mProgramInfoMap.size(); index++) { + Identifier id = other.mProgramInfoMap.keyAt(index); if (!passesFilter(id)) { continue; } - removed.remove(id); + ArrayMap<UniqueProgramIdentifier, RadioManager.ProgramInfo> entries = + other.mProgramInfoMap.valueAt(index); + for (int entryIndex = 0; entryIndex < entries.size(); entryIndex++) { + removed.remove(entries.keyAt(entryIndex)); - RadioManager.ProgramInfo newInfo = entry.getValue(); - if (!shouldIncludeInModified(newInfo)) { - continue; + RadioManager.ProgramInfo newInfo = entries.valueAt(entryIndex); + if (!shouldIncludeInModified(newInfo)) { + continue; + } + putInfo(newInfo); + modified.add(newInfo); } - mProgramInfoMap.put(id, newInfo); - modified.add(newInfo); } - for (ProgramSelector.Identifier rem : removed) { - mProgramInfoMap.remove(rem); + for (int removedIndex = 0; removedIndex < removed.size(); removedIndex++) { + removeUniqueId(removed.valueAt(removedIndex)); } mComplete = other.mComplete; return buildChunks(purge, mComplete, modified, maxNumModifiedPerChunk, removed, maxNumRemovedPerChunk); } - @Nullable List<ProgramList.Chunk> filterAndApplyChunk(@NonNull ProgramList.Chunk chunk) { + @Nullable + List<ProgramList.Chunk> filterAndApplyChunk(ProgramListChunk chunk) { return filterAndApplyChunkInternal(chunk, MAX_NUM_MODIFIED_PER_CHUNK, MAX_NUM_REMOVED_PER_CHUNK); } @VisibleForTesting - @Nullable List<ProgramList.Chunk> filterAndApplyChunkInternal(@NonNull ProgramList.Chunk chunk, + @Nullable + List<ProgramList.Chunk> filterAndApplyChunkInternal(ProgramListChunk chunk, int maxNumModifiedPerChunk, int maxNumRemovedPerChunk) { - if (chunk.isPurge()) { + if (chunk.purge) { mProgramInfoMap.clear(); } - Set<RadioManager.ProgramInfo> modified = new HashSet<>(); - Set<ProgramSelector.Identifier> removed = new HashSet<>(); - for (RadioManager.ProgramInfo info : chunk.getModified()) { - ProgramSelector.Identifier id = info.getSelector().getPrimaryId(); - if (!passesFilter(id) || !shouldIncludeInModified(info)) { + Set<RadioManager.ProgramInfo> modified = new ArraySet<>(); + for (android.hardware.broadcastradio.V2_0.ProgramInfo halProgramInfo : chunk.modified) { + RadioManager.ProgramInfo info = Convert.programInfoFromHal(halProgramInfo); + Identifier primaryId = info.getSelector().getPrimaryId(); + if (!passesFilter(primaryId) || !shouldIncludeInModified(info)) { continue; } - mProgramInfoMap.put(id, info); + putInfo(info); modified.add(info); } - for (ProgramSelector.Identifier id : chunk.getRemoved()) { - if (mProgramInfoMap.containsKey(id)) { - mProgramInfoMap.remove(id); - removed.add(id); + Set<UniqueProgramIdentifier> removed = new ArraySet<>(); + for (android.hardware.broadcastradio.V2_0.ProgramIdentifier halProgramId : chunk.removed) { + Identifier removedId = Convert.programIdentifierFromHal(halProgramId); + if (removedId == null) { + continue; + } + if (mProgramInfoMap.containsKey(removedId)) { + removed.addAll(mProgramInfoMap.get(removedId).keySet()); + mProgramInfoMap.remove(removedId); } } - if (modified.isEmpty() && removed.isEmpty() && mComplete == chunk.isComplete() - && !chunk.isPurge()) { + if (modified.isEmpty() && removed.isEmpty() && mComplete == chunk.complete + && !chunk.purge) { return null; } - mComplete = chunk.isComplete(); - return buildChunks(chunk.isPurge(), mComplete, modified, maxNumModifiedPerChunk, removed, + mComplete = chunk.complete; + return buildChunks(chunk.purge, mComplete, modified, maxNumModifiedPerChunk, removed, maxNumRemovedPerChunk); } - private boolean passesFilter(ProgramSelector.Identifier id) { + private boolean passesFilter(Identifier id) { if (mFilter == null) { return true; } @@ -215,9 +231,33 @@ final class ProgramInfoCache { return true; } + private void putInfo(RadioManager.ProgramInfo info) { + Identifier primaryId = info.getSelector().getPrimaryId(); + if (!mProgramInfoMap.containsKey(primaryId)) { + mProgramInfoMap.put(primaryId, new ArrayMap<>()); + } + mProgramInfoMap.get(primaryId).put(new UniqueProgramIdentifier( + info.getSelector()), info); + } + + private void removeUniqueId(UniqueProgramIdentifier uniqueId) { + Identifier primaryId = uniqueId.getPrimaryId(); + if (!mProgramInfoMap.containsKey(primaryId)) { + return; + } + mProgramInfoMap.get(primaryId).remove(uniqueId); + if (mProgramInfoMap.get(primaryId).isEmpty()) { + mProgramInfoMap.remove(primaryId); + } + } + private boolean shouldIncludeInModified(RadioManager.ProgramInfo newInfo) { - RadioManager.ProgramInfo oldInfo = mProgramInfoMap.get( - newInfo.getSelector().getPrimaryId()); + Identifier primaryId = newInfo.getSelector().getPrimaryId(); + RadioManager.ProgramInfo oldInfo = null; + if (mProgramInfoMap.containsKey(primaryId)) { + UniqueProgramIdentifier uniqueId = new UniqueProgramIdentifier(newInfo.getSelector()); + oldInfo = mProgramInfoMap.get(primaryId).get(uniqueId); + } if (oldInfo == null) { return true; } @@ -231,9 +271,9 @@ final class ProgramInfoCache { return (numerator / denominator) + (numerator % denominator > 0 ? 1 : 0); } - private static @NonNull List<ProgramList.Chunk> buildChunks(boolean purge, boolean complete, + private static List<ProgramList.Chunk> buildChunks(boolean purge, boolean complete, @Nullable Collection<RadioManager.ProgramInfo> modified, int maxNumModifiedPerChunk, - @Nullable Collection<ProgramSelector.Identifier> removed, int maxNumRemovedPerChunk) { + @Nullable Collection<UniqueProgramIdentifier> removed, int maxNumRemovedPerChunk) { // Communication protocol requires that if purge is set, removed is empty. if (purge) { removed = null; @@ -257,7 +297,7 @@ final class ProgramInfoCache { int modifiedPerChunk = 0; int removedPerChunk = 0; Iterator<RadioManager.ProgramInfo> modifiedIter = null; - Iterator<ProgramSelector.Identifier> removedIter = null; + Iterator<UniqueProgramIdentifier> removedIter = null; if (modified != null) { modifiedPerChunk = roundUpFraction(modified.size(), numChunks); modifiedIter = modified.iterator(); @@ -268,8 +308,8 @@ final class ProgramInfoCache { } List<ProgramList.Chunk> chunks = new ArrayList<ProgramList.Chunk>(numChunks); for (int i = 0; i < numChunks; i++) { - HashSet<RadioManager.ProgramInfo> modifiedChunk = new HashSet<>(); - HashSet<ProgramSelector.Identifier> removedChunk = new HashSet<>(); + ArraySet<RadioManager.ProgramInfo> modifiedChunk = new ArraySet<>(); + ArraySet<UniqueProgramIdentifier> removedChunk = new ArraySet<>(); if (modifiedIter != null) { for (int j = 0; j < modifiedPerChunk && modifiedIter.hasNext(); j++) { modifiedChunk.add(modifiedIter.next()); diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java index 7b5cb898b6b5..a54af2ef6e44 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java @@ -111,13 +111,11 @@ final class RadioModule { @Override public void onProgramListUpdated(ProgramListChunk programListChunk) { fireLater(() -> { - android.hardware.radio.ProgramList.Chunk chunk = - Convert.programListChunkFromHal(programListChunk); synchronized (mLock) { - mProgramInfoCache.filterAndApplyChunk(chunk); + mProgramInfoCache.filterAndApplyChunk(programListChunk); for (TunerSession tunerSession : mAidlTunerSessions) { - tunerSession.onMergedProgramListUpdateFromHal(chunk); + tunerSession.onMergedProgramListUpdateFromHal(programListChunk); } } }); diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java index 1efc4a50aa08..978dc01d1219 100644 --- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java +++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.graphics.Bitmap; import android.hardware.broadcastradio.V2_0.ConfigFlag; import android.hardware.broadcastradio.V2_0.ITunerSession; +import android.hardware.broadcastradio.V2_0.ProgramListChunk; import android.hardware.broadcastradio.V2_0.Result; import android.hardware.radio.ITuner; import android.hardware.radio.ProgramList; @@ -267,7 +268,7 @@ class TunerSession extends ITuner.Stub { } } - void onMergedProgramListUpdateFromHal(ProgramList.Chunk mergedChunk) { + void onMergedProgramListUpdateFromHal(ProgramListChunk mergedChunk) { List<ProgramList.Chunk> clientUpdateChunks = null; synchronized (mLock) { if (mProgramInfoCache == null) { diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java index 4d3bf4007e92..b5a373e35571 100644 --- a/services/core/java/com/android/server/pm/DeletePackageHelper.java +++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java @@ -464,10 +464,7 @@ final class DeletePackageHelper { if (DEBUG_REMOVE) Slog.d(TAG, "Still installed by other users"); clearPackageStateAndReturn = true; } else { - // We need to set it back to 'installed' so the uninstall - // broadcasts will be sent correctly. if (DEBUG_REMOVE) Slog.d(TAG, "Not installed by other users, full delete"); - ps.setInstalled(true, userId); mPm.mSettings.writeKernelMappingLPr(ps); clearPackageStateAndReturn = false; } diff --git a/services/core/java/com/android/server/pm/PackageArchiverService.java b/services/core/java/com/android/server/pm/PackageArchiverService.java index c7f067be8581..e0524077e9c1 100644 --- a/services/core/java/com/android/server/pm/PackageArchiverService.java +++ b/services/core/java/com/android/server/pm/PackageArchiverService.java @@ -16,6 +16,7 @@ package com.android.server.pm; +import static android.app.ComponentOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED; import static android.content.pm.PackageManager.DELETE_KEEP_DATA; import static android.os.PowerExemptionManager.REASON_PACKAGE_UNARCHIVE; import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED; @@ -24,6 +25,7 @@ import android.Manifest; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; +import android.annotation.UserIdInt; import android.app.AppOpsManager; import android.app.BroadcastOptions; import android.content.Context; @@ -33,24 +35,37 @@ import android.content.pm.IPackageArchiverService; import android.content.pm.LauncherActivityInfo; import android.content.pm.LauncherApps; import android.content.pm.PackageArchiver; +import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.VersionedPackage; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; import android.os.Binder; import android.os.Bundle; +import android.os.Environment; import android.os.ParcelableException; +import android.os.SELinux; import android.os.UserHandle; import android.text.TextUtils; +import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.server.pm.pkg.ArchiveState; import com.android.server.pm.pkg.ArchiveState.ArchiveActivityInfo; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageUserStateInternal; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.concurrent.CompletableFuture; /** * Responsible archiving apps and returning information about archived apps. @@ -61,6 +76,8 @@ import java.util.Objects; */ public class PackageArchiverService extends IPackageArchiverService.Stub { + private static final String TAG = "PackageArchiverService"; + /** * The maximum time granted for an app store to start a foreground service when unarchival * is requested. @@ -68,6 +85,8 @@ public class PackageArchiverService extends IPackageArchiverService.Stub { // TODO(b/297358628) Make this configurable through a flag. private static final int DEFAULT_UNARCHIVE_FOREGROUND_TIMEOUT_MS = 120 * 1000; + private static final String ARCHIVE_ICONS_DIR = "package_archiver"; + private final Context mContext; private final PackageManagerService mPm; @@ -97,25 +116,44 @@ public class PackageArchiverService extends IPackageArchiverService.Stub { snapshot.enforceCrossUserPermission(binderUid, userId, true, true, "archiveApp"); verifyCaller(providedUid, binderUid); - ArchiveState archiveState; + CompletableFuture<ArchiveState> archiveStateFuture; try { - archiveState = createArchiveState(packageName, userId); - // TODO(b/282952870) Should be reverted if uninstall fails/cancels - storeArchiveState(packageName, archiveState, userId); + archiveStateFuture = createArchiveState(packageName, userId); } catch (PackageManager.NameNotFoundException e) { + Slog.d(TAG, TextUtils.formatSimple("Failed to archive %s with message %s", + packageName, e.getMessage())); throw new ParcelableException(e); } - // TODO(b/278553670) Add special strings for the delete dialog - mPm.mInstallerService.uninstall( - new VersionedPackage(packageName, PackageManager.VERSION_CODE_HIGHEST), - callerPackageName, DELETE_KEEP_DATA, intentSender, userId); + archiveStateFuture + .thenAccept( + archiveState -> { + // TODO(b/282952870) Should be reverted if uninstall fails/cancels + try { + storeArchiveState(packageName, archiveState, userId); + } catch (PackageManager.NameNotFoundException e) { + sendFailureStatus(intentSender, packageName, e.getMessage()); + return; + } + + // TODO(b/278553670) Add special strings for the delete dialog + mPm.mInstallerService.uninstall( + new VersionedPackage(packageName, + PackageManager.VERSION_CODE_HIGHEST), + callerPackageName, DELETE_KEEP_DATA, intentSender, userId, + binderUid); + }) + .exceptionally( + e -> { + sendFailureStatus(intentSender, packageName, e.getMessage()); + return null; + }); } /** * Creates archived state for the package and user. */ - public ArchiveState createArchiveState(String packageName, int userId) + public CompletableFuture<ArchiveState> createArchiveState(String packageName, int userId) throws PackageManager.NameNotFoundException { PackageStateInternal ps = getPackageState(packageName, mPm.snapshotComputer(), Binder.getCallingUid(), userId); @@ -123,16 +161,56 @@ public class PackageArchiverService extends IPackageArchiverService.Stub { verifyInstaller(responsibleInstallerPackage); List<LauncherActivityInfo> mainActivities = getLauncherActivityInfos(ps, userId); + final CompletableFuture<ArchiveState> archiveState = new CompletableFuture<>(); + mPm.mHandler.post(() -> { + try { + archiveState.complete( + createArchiveStateInternal(packageName, userId, mainActivities, + responsibleInstallerPackage)); + } catch (IOException e) { + archiveState.completeExceptionally(e); + } + }); + return archiveState; + } + + private ArchiveState createArchiveStateInternal(String packageName, int userId, + List<LauncherActivityInfo> mainActivities, String installerPackage) + throws IOException { List<ArchiveActivityInfo> archiveActivityInfos = new ArrayList<>(); for (int i = 0; i < mainActivities.size(); i++) { - // TODO(b/278553670) Extract and store launcher icons + LauncherActivityInfo mainActivity = mainActivities.get(i); + Path iconPath = storeIcon(packageName, mainActivity, userId); ArchiveActivityInfo activityInfo = new ArchiveActivityInfo( - mainActivities.get(i).getLabel().toString(), - Path.of("/TODO"), null); + mainActivity.getLabel().toString(), iconPath, null); archiveActivityInfos.add(activityInfo); } - return new ArchiveState(archiveActivityInfos, responsibleInstallerPackage); + return new ArchiveState(archiveActivityInfos, installerPackage); + } + + // TODO(b/298452477) Handle monochrome icons. + @VisibleForTesting + Path storeIcon(String packageName, LauncherActivityInfo mainActivity, + @UserIdInt int userId) + throws IOException { + int iconResourceId = mainActivity.getActivityInfo().getIconResource(); + if (iconResourceId == 0) { + // The app doesn't define an icon. No need to store anything. + return null; + } + File iconsDir = createIconsDir(userId); + File iconFile = new File(iconsDir, packageName + "-" + mainActivity.getName() + ".png"); + Bitmap icon = drawableToBitmap(mainActivity.getIcon(/* density= */ 0)); + try (FileOutputStream out = new FileOutputStream(iconFile)) { + // Note: Quality is ignored for PNGs. + if (!icon.compress(Bitmap.CompressFormat.PNG, /* quality= */ 100, out)) { + throw new IOException(TextUtils.formatSimple("Failure to store icon file %s", + iconFile.getName())); + } + out.flush(); + } + return iconFile.toPath(); } private void verifyInstaller(String installerPackage) @@ -313,6 +391,29 @@ public class PackageArchiverService extends IPackageArchiverService.Stub { return ps; } + private void sendFailureStatus(IntentSender statusReceiver, String packageName, + String message) { + Slog.d(TAG, TextUtils.formatSimple("Failed to archive %s with message %s", packageName, + message)); + final Intent fillIn = new Intent(); + fillIn.putExtra(PackageInstaller.EXTRA_PACKAGE_NAME, packageName); + fillIn.putExtra(PackageInstaller.EXTRA_STATUS, PackageInstaller.STATUS_FAILURE); + fillIn.putExtra(PackageInstaller.EXTRA_STATUS_MESSAGE, message); + try { + final BroadcastOptions options = BroadcastOptions.makeBasic(); + options.setPendingIntentBackgroundActivityStartMode( + MODE_BACKGROUND_ACTIVITY_START_DENIED); + statusReceiver.sendIntent(mContext, 0, fillIn, /* onFinished= */ null, + /* handler= */ null, /* requiredPermission= */ null, options.toBundle()); + } catch (IntentSender.SendIntentException e) { + Slog.e( + TAG, + TextUtils.formatSimple("Failed to send failure status for %s with message %s", + packageName, message), + e); + } + } + private static void verifyCaller(int providedUid, int binderUid) { if (providedUid != binderUid) { throw new SecurityException( @@ -323,4 +424,44 @@ public class PackageArchiverService extends IPackageArchiverService.Stub { binderUid)); } } + + private File createIconsDir(@UserIdInt int userId) throws IOException { + File iconsDir = getIconsDir(userId); + if (!iconsDir.isDirectory()) { + iconsDir.delete(); + iconsDir.mkdirs(); + if (!iconsDir.isDirectory()) { + throw new IOException("Unable to create directory " + iconsDir); + } + } + SELinux.restorecon(iconsDir); + return iconsDir; + } + + private File getIconsDir(int userId) { + return new File(Environment.getDataSystemCeDirectory(userId), ARCHIVE_ICONS_DIR); + } + + private static Bitmap drawableToBitmap(Drawable drawable) { + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + + } + + Bitmap bitmap; + if (drawable.getIntrinsicWidth() <= 0 || drawable.getIntrinsicHeight() <= 0) { + // Needed for drawables that are just a single color. + bitmap = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); + } else { + bitmap = + Bitmap.createBitmap( + drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), + Bitmap.Config.ARGB_8888); + } + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + return bitmap; + } } diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index e3602565ef5b..fabef7609546 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -1240,8 +1240,18 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements @Override public void uninstall(VersionedPackage versionedPackage, String callerPackageName, int flags, IntentSender statusReceiver, int userId) { + uninstall( + versionedPackage, + callerPackageName, + flags, + statusReceiver, + userId, + Binder.getCallingUid()); + } + + void uninstall(VersionedPackage versionedPackage, String callerPackageName, int flags, + IntentSender statusReceiver, int userId, int callingUid) { final Computer snapshot = mPm.snapshotComputer(); - final int callingUid = Binder.getCallingUid(); snapshot.enforceCrossUserPermission(callingUid, userId, true, true, "uninstall"); if (!PackageManagerServiceUtils.isRootOrShell(callingUid)) { mAppOps.checkPackage(callingUid, callerPackageName); @@ -1257,7 +1267,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements final PackageDeleteObserverAdapter adapter = new PackageDeleteObserverAdapter(mContext, statusReceiver, versionedPackage.getPackageName(), canSilentlyInstallPackage, userId); - if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DELETE_PACKAGES) + if (mContext.checkCallingOrSelfPermission(Manifest.permission.DELETE_PACKAGES) == PackageManager.PERMISSION_GRANTED) { // Sweet, call straight through! mPm.deletePackageVersioned(versionedPackage, adapter.getBinder(), userId, flags); diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java index e8e647010b82..0dd4111adbfa 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerSession.java +++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java @@ -3641,9 +3641,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub { @GuardedBy("mLock") private void maybeStageFsveritySignatureLocked(File origFile, File targetFile, boolean fsVerityRequired) throws PackageManagerException { - if (com.android.server.security.Flags.deprecateFsvSig()) { - return; - } final File originalSignature = new File( VerityUtils.getFsveritySignatureFilePath(origFile.getPath())); if (originalSignature.exists()) { diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index 04232494a026..2028231ab36b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -543,9 +543,6 @@ public class PackageManagerServiceUtils { /** Returns true if standard APK Verity is enabled. */ static boolean isApkVerityEnabled() { - if (com.android.server.security.Flags.deprecateFsvSig()) { - return false; - } return Build.VERSION.DEVICE_INITIAL_SDK_INT >= Build.VERSION_CODES.R || SystemProperties.getInt("ro.apk_verity.mode", FSVERITY_DISABLED) == FSVERITY_ENABLED; diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index d9f1df5e02c9..a0c9cd1757c3 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -2784,33 +2784,111 @@ class PackageManagerShellCommand extends ShellCommand { private int runGrantRevokePermission(boolean grant) throws RemoteException { int userId = UserHandle.USER_SYSTEM; - String opt = null; + String opt; + boolean allPermissions = false; while ((opt = getNextOption()) != null) { if (opt.equals("--user")) { userId = UserHandle.parseUserArg(getNextArgRequired()); } + if (opt.equals("--all-permissions")) { + allPermissions = true; + } } String pkg = getNextArg(); - if (pkg == null) { + if (!allPermissions && pkg == null) { getErrPrintWriter().println("Error: no package specified"); return 1; } String perm = getNextArg(); - if (perm == null) { + if (!allPermissions && perm == null) { getErrPrintWriter().println("Error: no permission specified"); return 1; } + if (allPermissions && perm != null) { + getErrPrintWriter().println("Error: permission specified but not expected"); + return 1; + } final UserHandle translatedUser = UserHandle.of(translateUserId(userId, UserHandle.USER_NULL, "runGrantRevokePermission")); - if (grant) { - mPermissionManager.grantRuntimePermission(pkg, perm, translatedUser); + + List<PackageInfo> packageInfos; + if (pkg == null) { + packageInfos = mContext.getPackageManager().getInstalledPackages( + PackageManager.GET_PERMISSIONS); } else { - mPermissionManager.revokeRuntimePermission(pkg, perm, translatedUser, null); + try { + packageInfos = Collections.singletonList( + mContext.getPackageManager().getPackageInfo(pkg, + PackageManager.GET_PERMISSIONS)); + } catch (NameNotFoundException e) { + getErrPrintWriter().println("Error: package not found"); + return 1; + } + } + + for (PackageInfo packageInfo : packageInfos) { + List<String> permissions = Collections.singletonList(perm); + if (allPermissions) { + permissions = getRequestedRuntimePermissions(packageInfo); + } + for (String permission : permissions) { + if (grant) { + try { + mPermissionManager.grantRuntimePermission(packageInfo.packageName, + permission, + translatedUser); + } catch (Exception e) { + if (!allPermissions) { + throw e; + } else { + Slog.w(TAG, "Could not grant permission " + permission, e); + } + } + } else { + try { + mPermissionManager.revokeRuntimePermission(packageInfo.packageName, + permission, + translatedUser, null); + } catch (Exception e) { + if (!allPermissions) { + throw e; + } else { + Slog.w(TAG, "Could not grant permission " + permission, e); + } + } + } + } } return 0; } + private List<String> getRequestedRuntimePermissions(PackageInfo info) { + // No requested permissions + if (info.requestedPermissions == null) { + return new ArrayList<>(); + } + List<String> result = new ArrayList<>(); + PackageManager pm = mContext.getPackageManager(); + // Iterate through requested permissions for denied ones + for (String permission : info.requestedPermissions) { + PermissionInfo pi = null; + try { + pi = pm.getPermissionInfo(permission, 0); + } catch (NameNotFoundException nnfe) { + // ignore + } + if (pi == null) { + continue; + } + if (pi.getProtection() != PermissionInfo.PROTECTION_DANGEROUS) { + continue; + } + result.add(permission); + } + return result; + } + private int runResetPermissions() throws RemoteException { mLegacyPermissionManager.resetRuntimePermissions(); return 0; @@ -4643,11 +4721,15 @@ class PackageManagerShellCommand extends ShellCommand { pw.println(" get-distracting-restriction [--user USER_ID] PACKAGE [PACKAGE...]"); pw.println(" Gets the specified restriction flags of given package(s) (of the user)."); pw.println(""); - pw.println(" grant [--user USER_ID] PACKAGE PERMISSION"); - pw.println(" revoke [--user USER_ID] PACKAGE PERMISSION"); + pw.println(" grant [--user USER_ID] [--all-permissions] PACKAGE PERMISSION"); + pw.println(" revoke [--user USER_ID] [--all-permissions] PACKAGE PERMISSION"); pw.println(" These commands either grant or revoke permissions to apps. The permissions"); pw.println(" must be declared as used in the app's manifest, be runtime permissions"); pw.println(" (protection level dangerous), and the app targeting SDK greater than Lollipop MR1."); + pw.println(" Flags are:"); + pw.println(" --user: Specifies the user for which the operation needs to be performed"); + pw.println(" --all-permissions: If specified all the missing runtime permissions will"); + pw.println(" be granted to the PACKAGE or to all the packages if none is specified."); pw.println(""); pw.println(" set-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]"); pw.println(" clear-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]"); diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 88184c0cb490..114f80d7998f 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -35,6 +35,7 @@ import android.content.pm.overlay.OverlayPaths; import android.os.UserHandle; import android.os.incremental.IncrementalManager; import android.service.pm.PackageProto; +import android.service.pm.PackageProto.UserInfoProto.ArchiveState.ArchiveActivityInfo; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -1161,18 +1162,15 @@ public class PackageSetting extends SettingBase implements PackageStateInternal for (ArchiveState.ArchiveActivityInfo activityInfo : archiveState.getActivityInfos()) { long activityInfoToken = proto.start( PackageProto.UserInfoProto.ArchiveState.ACTIVITY_INFOS); - proto.write(PackageProto.UserInfoProto.ArchiveState.ArchiveActivityInfo.TITLE, - activityInfo.getTitle()); - proto.write( - PackageProto.UserInfoProto.ArchiveState.ArchiveActivityInfo.ICON_BITMAP_PATH, - activityInfo.getIconBitmap().toAbsolutePath().toString()); - proto.write( - PackageProto - .UserInfoProto - .ArchiveState - .ArchiveActivityInfo - .MONOCHROME_ICON_BITMAP_PATH, - activityInfo.getMonochromeIconBitmap().toAbsolutePath().toString()); + proto.write(ArchiveActivityInfo.TITLE, activityInfo.getTitle()); + if (activityInfo.getIconBitmap() != null) { + proto.write(ArchiveActivityInfo.ICON_BITMAP_PATH, + activityInfo.getIconBitmap().toAbsolutePath().toString()); + } + if (activityInfo.getMonochromeIconBitmap() != null) { + proto.write(ArchiveActivityInfo.MONOCHROME_ICON_BITMAP_PATH, + activityInfo.getMonochromeIconBitmap().toAbsolutePath().toString()); + } proto.end(activityInfoToken); } diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java index 2aedf0d8960c..8dec425f074d 100644 --- a/services/core/java/com/android/server/pm/RemovePackageHelper.java +++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java @@ -22,7 +22,6 @@ import static android.os.incremental.IncrementalManager.isIncrementalPath; import static android.os.storage.StorageManager.FLAG_STORAGE_CE; import static android.os.storage.StorageManager.FLAG_STORAGE_DE; import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL; - import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets; import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL; import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE; @@ -400,6 +399,21 @@ final class RemovePackageHelper { changedUsers); mPm.postPreferredActivityChangedBroadcast(UserHandle.USER_ALL); } + } else if (!deletedPs.isSystem() && outInfo != null && !outInfo.mIsUpdate + && outInfo.mRemovedUsers != null) { + // For non-system uninstalls with DELETE_KEEP_DATA, set the installed state to false + // for affected users. This does not apply to app updates where the old apk is replaced + // but the old data remains. + if (DEBUG_REMOVE) { + Slog.d(TAG, "Updating installed state to false because of DELETE_KEEP_DATA"); + } + for (int userId : outInfo.mRemovedUsers) { + if (DEBUG_REMOVE) { + final boolean wasInstalled = deletedPs.getInstalled(userId); + Slog.d(TAG, " user " + userId + ": " + wasInstalled + " => " + false); + } + deletedPs.setInstalled(/* installed= */ false, userId); + } } // make sure to preserve per-user installed state if this removal was just // a downgrade of a system app to the factory package diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 1137681de5cf..111a32d03b4c 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -2062,8 +2062,9 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile if (tagName.equals(TAG_ARCHIVE_ACTIVITY_INFO)) { String title = parser.getAttributeValue(null, ATTR_ARCHIVE_ACTIVITY_TITLE); - Path iconPath = Path.of(parser.getAttributeValue(null, - ATTR_ARCHIVE_ICON_PATH)); + String iconAttribute = parser.getAttributeValue(null, + ATTR_ARCHIVE_ICON_PATH); + Path iconPath = iconAttribute == null ? null : Path.of(iconAttribute); String monochromeAttribute = parser.getAttributeValue(null, ATTR_ARCHIVE_MONOCHROME_ICON_PATH); Path monochromeIconPath = monochromeAttribute == null ? null : Path.of( @@ -2447,8 +2448,10 @@ public final class Settings implements Watchable, Snappable, ResilientAtomicFile for (ArchiveState.ArchiveActivityInfo activityInfo : archiveState.getActivityInfos()) { serializer.startTag(null, TAG_ARCHIVE_ACTIVITY_INFO); serializer.attribute(null, ATTR_ARCHIVE_ACTIVITY_TITLE, activityInfo.getTitle()); - serializer.attribute(null, ATTR_ARCHIVE_ICON_PATH, - activityInfo.getIconBitmap().toAbsolutePath().toString()); + if (activityInfo.getIconBitmap() != null) { + serializer.attribute(null, ATTR_ARCHIVE_ICON_PATH, + activityInfo.getIconBitmap().toAbsolutePath().toString()); + } if (activityInfo.getMonochromeIconBitmap() != null) { serializer.attribute(null, ATTR_ARCHIVE_MONOCHROME_ICON_PATH, activityInfo.getMonochromeIconBitmap().toAbsolutePath().toString()); diff --git a/services/core/java/com/android/server/pm/pkg/ArchiveState.java b/services/core/java/com/android/server/pm/pkg/ArchiveState.java index d44ae1652da5..4916a4a6d72a 100644 --- a/services/core/java/com/android/server/pm/pkg/ArchiveState.java +++ b/services/core/java/com/android/server/pm/pkg/ArchiveState.java @@ -56,8 +56,11 @@ public class ArchiveState { @NonNull private final String mTitle; - /** The path to the stored icon of the activity in the app's locale. */ - @NonNull + /** + * The path to the stored icon of the activity in the app's locale. Null if the app does + * not define any icon (default icon would be shown on the launcher). + */ + @Nullable private final Path mIconBitmap; /** See {@link #mIconBitmap}. Only set if the app defined a monochrome icon. */ @@ -85,21 +88,20 @@ public class ArchiveState { * @param title * Corresponds to the activity's android:label in the app's locale. * @param iconBitmap - * The path to the stored icon of the activity in the app's locale. + * The path to the stored icon of the activity in the app's locale. Null if the app does + * not define any icon (default icon would be shown on the launcher). * @param monochromeIconBitmap * See {@link #mIconBitmap}. Only set if the app defined a monochrome icon. */ @DataClass.Generated.Member public ArchiveActivityInfo( @NonNull String title, - @NonNull Path iconBitmap, + @Nullable Path iconBitmap, @Nullable Path monochromeIconBitmap) { this.mTitle = title; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mTitle); this.mIconBitmap = iconBitmap; - com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, mIconBitmap); this.mMonochromeIconBitmap = monochromeIconBitmap; // onConstructed(); // You can define this method to get a callback @@ -114,10 +116,11 @@ public class ArchiveState { } /** - * The path to the stored icon of the activity in the app's locale. + * The path to the stored icon of the activity in the app's locale. Null if the app does + * not define any icon (default icon would be shown on the launcher). */ @DataClass.Generated.Member - public @NonNull Path getIconBitmap() { + public @Nullable Path getIconBitmap() { return mIconBitmap; } @@ -174,10 +177,10 @@ public class ArchiveState { } @DataClass.Generated( - time = 1689169065133L, + time = 1693590309015L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/ArchiveState.java", - inputSignatures = "private final @android.annotation.NonNull java.lang.String mTitle\nprivate final @android.annotation.NonNull java.nio.file.Path mIconBitmap\nprivate final @android.annotation.Nullable java.nio.file.Path mMonochromeIconBitmap\nclass ArchiveActivityInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)") + inputSignatures = "private final @android.annotation.NonNull java.lang.String mTitle\nprivate final @android.annotation.Nullable java.nio.file.Path mIconBitmap\nprivate final @android.annotation.Nullable java.nio.file.Path mMonochromeIconBitmap\nclass ArchiveActivityInfo extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)") @Deprecated private void __metadata() {} @@ -292,7 +295,7 @@ public class ArchiveState { } @DataClass.Generated( - time = 1689169065144L, + time = 1693590309027L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/ArchiveState.java", inputSignatures = "private final @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.ArchiveActivityInfo> mActivityInfos\nprivate final @android.annotation.NonNull java.lang.String mInstallerTitle\nclass ArchiveState extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true)") diff --git a/services/core/java/com/android/server/security/FileIntegrityService.java b/services/core/java/com/android/server/security/FileIntegrityService.java index 0879d9575c97..3aed6e30cf87 100644 --- a/services/core/java/com/android/server/security/FileIntegrityService.java +++ b/services/core/java/com/android/server/security/FileIntegrityService.java @@ -90,13 +90,6 @@ public class FileIntegrityService extends SystemService { @NonNull String packageName) { checkCallerPermission(packageName); - if (Flags.deprecateFsvSig()) { - // When deprecated, stop telling the caller that any app source certificate is - // trusted on the current device. This behavior is also consistent with devices - // without this feature support. - return false; - } - try { if (!VerityUtils.isFsVeritySupported()) { return false; diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java index d430dda1b463..b823e7353a84 100644 --- a/services/core/java/com/android/server/wm/ActivityClientController.java +++ b/services/core/java/com/android/server/wm/ActivityClientController.java @@ -1170,9 +1170,7 @@ class ActivityClientController extends IActivityClientController.Stub { fullscreenRequest, r); reportMultiwindowFullscreenRequestValidatingResult(callback, validateResult); if (validateResult != RESULT_APPROVED) { - if (queued) { - transition.abort(); - } + transition.abort(); return; } transition.collect(topFocusedRootTask); diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index f47007b28e5b..4aea70c6dd64 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -3659,6 +3659,9 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { synchronized (mGlobalLock) { if (r.getParent() == null) { Slog.e(TAG, "Skip enterPictureInPictureMode, destroyed " + r); + if (transition != null) { + transition.abort(); + } return; } EventLogTags.writeWmEnterPip(r.mUserId, System.identityHashCode(r), diff --git a/services/core/java/com/android/server/wm/ContentRecorder.java b/services/core/java/com/android/server/wm/ContentRecorder.java index 5aa7c97ecb08..f0e4149a9159 100644 --- a/services/core/java/com/android/server/wm/ContentRecorder.java +++ b/services/core/java/com/android/server/wm/ContentRecorder.java @@ -35,6 +35,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.provider.DeviceConfig; import android.view.ContentRecordingSession; +import android.view.ContentRecordingSession.RecordContent; import android.view.Display; import android.view.SurfaceControl; @@ -84,6 +85,7 @@ final class ContentRecorder implements WindowContainerListener { /** * The last configuration orientation. */ + @Configuration.Orientation private int mLastOrientation = ORIENTATION_UNDEFINED; ContentRecorder(@NonNull DisplayContent displayContent) { @@ -156,7 +158,8 @@ final class ContentRecorder implements WindowContainerListener { // Retrieve the size of the region to record, and continue with the update // if the bounds or orientation has changed. final Rect recordedContentBounds = mRecordedWindowContainer.getBounds(); - int recordedContentOrientation = mRecordedWindowContainer.getOrientation(); + @Configuration.Orientation int recordedContentOrientation = + mRecordedWindowContainer.getConfiguration().orientation; if (!mLastRecordedBounds.equals(recordedContentBounds) || lastOrientation != recordedContentOrientation) { Point surfaceSize = fetchSurfaceSizeIfPresent(); @@ -356,7 +359,7 @@ final class ContentRecorder implements WindowContainerListener { */ @Nullable private WindowContainer retrieveRecordedWindowContainer() { - final int contentToRecord = mContentRecordingSession.getContentToRecord(); + @RecordContent final int contentToRecord = mContentRecordingSession.getContentToRecord(); final IBinder tokenToRecord = mContentRecordingSession.getTokenToRecord(); switch (contentToRecord) { case RECORD_CONTENT_DISPLAY: @@ -472,6 +475,12 @@ final class ContentRecorder implements WindowContainerListener { shiftedY = (surfaceSize.y - scaledHeight) / 2; } + ProtoLog.v(WM_DEBUG_CONTENT_RECORDING, + "Content Recording: Apply transformations of shift %d x %d, scale %f, crop %d x " + + "%d for display %d", + shiftedX, shiftedY, scale, recordedContentBounds.width(), + recordedContentBounds.height(), mDisplayContent.getDisplayId()); + transaction // Crop the area to capture to exclude the 'extra' wallpaper that is used // for parallax (b/189930234). diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 707b7799460e..395ab3a641b4 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -269,6 +269,8 @@ public class DisplayPolicy { private boolean mIsFreeformWindowOverlappingWithNavBar; + private @InsetsType int mForciblyShownTypes; + private boolean mIsImmersiveMode; // The windows we were told about in focusChanged. @@ -1402,6 +1404,7 @@ public class DisplayPolicy { mAllowLockscreenWhenOn = false; mShowingDream = false; mIsFreeformWindowOverlappingWithNavBar = false; + mForciblyShownTypes = 0; } /** @@ -1459,6 +1462,10 @@ public class DisplayPolicy { } } + if (win.mSession.mCanForceShowingInsets) { + mForciblyShownTypes |= win.mAttrs.forciblyShownTypes; + } + if (!affectsSystemUi) { return; } @@ -1640,6 +1647,10 @@ public class DisplayPolicy { mService.mPolicy.setAllowLockscreenWhenOn(getDisplayId(), mAllowLockscreenWhenOn); } + boolean areTypesForciblyShownTransiently(@InsetsType int types) { + return (mForciblyShownTypes & types) == types; + } + /** * Applies the keyguard policy to a specific window. * diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index 835c92d0a30d..03f025b1f0f4 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -23,8 +23,6 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.InsetsSource.ID_IME; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import android.annotation.NonNull; @@ -473,7 +471,7 @@ class InsetsPolicy { // we will dispatch the real visibility of status bar to the client. return mPermanentControlTarget; } - if (forceShowsStatusBarTransiently() && !fake) { + if (mPolicy.areTypesForciblyShownTransiently(Type.statusBars()) && !fake) { // Status bar is forcibly shown transiently, and its new visibility won't be // dispatched to the client so that we can keep the layout stable. We will dispatch the // fake control to the client, so that it can re-show the bar during this scenario. @@ -505,7 +503,7 @@ class InsetsPolicy { if (imeWin != null && imeWin.isVisible() && !mHideNavBarForKeyboard) { // Force showing navigation bar while IME is visible and if navigation bar is not // configured to be hidden by the IME. - return null; + return mPermanentControlTarget; } if (!fake && isTransient(Type.navigationBars())) { return mTransientControlTarget; @@ -533,7 +531,7 @@ class InsetsPolicy { // bar, and we will dispatch the real visibility of navigation bar to the client. return mPermanentControlTarget; } - if (forceShowsNavigationBarTransiently() && !fake) { + if (mPolicy.areTypesForciblyShownTransiently(Type.navigationBars()) && !fake) { // Navigation bar is forcibly shown transiently, and its new visibility won't be // dispatched to the client so that we can keep the layout stable. We will dispatch the // fake control to the client, so that it can re-show the bar during this scenario. @@ -603,17 +601,6 @@ class InsetsPolicy { && focusedWin.getAttrs().type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW; } - private boolean forceShowsStatusBarTransiently() { - final WindowState win = mPolicy.getStatusBar(); - return win != null && (win.mAttrs.privateFlags & PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR) != 0; - } - - private boolean forceShowsNavigationBarTransiently() { - final WindowState win = mPolicy.getNotificationShade(); - return win != null - && (win.mAttrs.privateFlags & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0; - } - private void dispatchTransientSystemBarsVisibilityChanged( @Nullable WindowState focusedWindow, boolean areVisible, diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index 1845ae8cd92b..0c45eea2d365 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -23,6 +23,7 @@ import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW; import static android.Manifest.permission.SET_UNRESTRICTED_GESTURE_EXCLUSION; import static android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS; import static android.Manifest.permission.START_TASKS_FROM_RECENTS; +import static android.Manifest.permission.STATUS_BAR_SERVICE; import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.content.ClipDescription.MIMETYPE_APPLICATION_ACTIVITY; @@ -108,6 +109,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { private final ArraySet<WindowSurfaceController> mAlertWindowSurfaces = new ArraySet<>(); private final DragDropController mDragDropController; final boolean mCanAddInternalSystemWindow; + final boolean mCanForceShowingInsets; private final boolean mCanStartTasksFromRecents; final boolean mCanCreateSystemApplicationOverlay; @@ -131,6 +133,9 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { mLastReportedAnimatorScale = service.getCurrentAnimatorScale(); mCanAddInternalSystemWindow = service.mContext.checkCallingOrSelfPermission( INTERNAL_SYSTEM_WINDOW) == PERMISSION_GRANTED; + mCanForceShowingInsets = service.mAtmService.isCallerRecents(mUid) + || service.mContext.checkCallingOrSelfPermission(STATUS_BAR_SERVICE) + == PERMISSION_GRANTED; mCanHideNonSystemOverlayWindows = service.mContext.checkCallingOrSelfPermission( HIDE_NON_SYSTEM_OVERLAY_WINDOWS) == PERMISSION_GRANTED || service.mContext.checkCallingOrSelfPermission(HIDE_OVERLAY_WINDOWS) diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index a6c64912edd3..843e6d154ecb 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -1487,6 +1487,11 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener { return; } + if (mState != STATE_STARTED) { + Slog.e(TAG, "Playing a Transition which hasn't started! #" + mSyncId + " This will " + + "likely cause an exception in Shell"); + } + mState = STATE_PLAYING; mStartTransaction = transaction; mFinishTransaction = mController.mAtm.mWindowManager.mTransactionFactory.get(); diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp index 55deb2203a03..176bc28389e5 100644 --- a/services/core/jni/com_android_server_input_InputManagerService.cpp +++ b/services/core/jni/com_android_server_input_InputManagerService.cpp @@ -42,6 +42,7 @@ #include <android_view_VerifiedMotionEvent.h> #include <batteryservice/include/batteryservice/BatteryServiceConstants.h> #include <binder/IServiceManager.h> +#include <com_android_input_flags.h> #include <input/Input.h> #include <input/PointerController.h> #include <input/SpriteController.h> @@ -81,6 +82,8 @@ static constexpr std::chrono::duration MAX_VIBRATE_PATTERN_DELAY = 100s; static constexpr std::chrono::milliseconds MAX_VIBRATE_PATTERN_DELAY_MILLIS = std::chrono::duration_cast<std::chrono::milliseconds>(MAX_VIBRATE_PATTERN_DELAY); +namespace input_flags = com::android::input::flags; + namespace android { // The exponent used to calculate the pointer speed scaling factor. @@ -733,7 +736,7 @@ std::shared_ptr<PointerControllerInterface> NativeInputManager::obtainPointerCon ensureSpriteControllerLocked(); static const bool ENABLE_POINTER_CHOREOGRAPHER = - sysprop::InputProperties::enable_pointer_choreographer().value_or(false); + input_flags::enable_pointer_choreographer(); // Disable the functionality of the legacy PointerController if PointerChoreographer is // enabled. diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java index b4a66bd75a6e..76b41b70cdf4 100644 --- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java +++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java @@ -1895,6 +1895,13 @@ public class MockingOomAdjusterTests { assertProcStates(app2, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ, SCHED_GROUP_DEFAULT); assertBfsl(app2); + + bindService(client2, app1, null, 0, mock(IBinder.class)); + bindService(app1, client2, null, 0, mock(IBinder.class)); + client2.mServices.setHasForegroundServices(false, 0, /* hasNoneType=*/false); + updateOomAdj(app1, client1, client2); + assertProcStates(app1, PROCESS_STATE_IMPORTANT_FOREGROUND, VISIBLE_APP_ADJ, + SCHED_GROUP_TOP_APP); } @SuppressWarnings("GuardedBy") diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java index 80576a688fdd..60b28d3a2ff0 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageArchiverServiceTest.java @@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; @@ -34,11 +35,15 @@ import android.app.AppOpsManager; import android.content.Context; import android.content.Intent; import android.content.IntentSender; +import android.content.pm.ActivityInfo; import android.content.pm.LauncherActivityInfo; import android.content.pm.LauncherApps; import android.content.pm.PackageArchiver; +import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.VersionedPackage; +import android.content.res.Resources; +import android.graphics.Bitmap; import android.os.Binder; import android.os.Build; import android.os.Bundle; @@ -62,6 +67,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; @@ -74,9 +80,10 @@ public class PackageArchiverServiceTest { private static final String PACKAGE = "com.example"; private static final String CALLER_PACKAGE = "com.caller"; private static final String INSTALLER_PACKAGE = "com.installer"; + private static final Path ICON_PATH = Path.of("icon.png"); @Rule - public final MockSystemRule mMockSystem = new MockSystemRule(); + public final MockSystemRule rule = new MockSystemRule(); @Mock private IntentSender mIntentSender; @@ -87,9 +94,13 @@ public class PackageArchiverServiceTest { @Mock private LauncherApps mLauncherApps; @Mock + private PackageManager mPackageManager; + @Mock private PackageInstallerService mInstallerService; @Mock private PackageStateInternal mPackageState; + @Mock + private Bitmap mIcon; private final InstallSource mInstallSource = InstallSource.create( @@ -102,7 +113,6 @@ public class PackageArchiverServiceTest { /* packageSource= */ 0); private final List<LauncherActivityInfo> mLauncherActivityInfos = createLauncherActivities(); - private final int mUserId = UserHandle.CURRENT.getIdentifier(); private PackageUserStateImpl mUserState; @@ -114,10 +124,10 @@ public class PackageArchiverServiceTest { @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mMockSystem.system().stageNominalSystemState(); - when(mMockSystem.mocks().getInjector().getPackageInstallerService()).thenReturn( + rule.system().stageNominalSystemState(); + when(rule.mocks().getInjector().getPackageInstallerService()).thenReturn( mInstallerService); - PackageManagerService pm = spy(new PackageManagerService(mMockSystem.mocks().getInjector(), + PackageManagerService pm = spy(new PackageManagerService(rule.mocks().getInjector(), /* factoryTest= */false, MockSystem.Companion.getDEFAULT_VERSION_INFO().fingerprint, /* isEngBuild= */ false, @@ -132,18 +142,27 @@ public class PackageArchiverServiceTest { when(mPackageState.getPackageName()).thenReturn(PACKAGE); when(mPackageState.getInstallSource()).thenReturn(mInstallSource); mPackageSetting = createBasicPackageSetting(); - when(mMockSystem.mocks().getSettings().getPackageLPr(eq(PACKAGE))).thenReturn( + when(rule.mocks().getSettings().getPackageLPr(eq(PACKAGE))).thenReturn( mPackageSetting); mUserState = new PackageUserStateImpl().setInstalled(true); mPackageSetting.setUserState(mUserId, mUserState); when(mPackageState.getUserStateOrDefault(eq(mUserId))).thenReturn(mUserState); + when(mContext.getSystemService(LauncherApps.class)).thenReturn(mLauncherApps); when(mLauncherApps.getActivityList(eq(PACKAGE), eq(UserHandle.CURRENT))).thenReturn( mLauncherActivityInfos); doReturn(mComputer).when(pm).snapshotComputer(); when(mComputer.getPackageUid(eq(CALLER_PACKAGE), eq(0L), eq(mUserId))).thenReturn( Binder.getCallingUid()); - mArchiveService = new PackageArchiverService(mContext, pm); + + when(mContext.getPackageManager()).thenReturn(mPackageManager); + when(mPackageManager.getResourcesForApplication(eq(PACKAGE))).thenReturn( + mock(Resources.class)); + when(mIcon.compress(eq(Bitmap.CompressFormat.PNG), eq(100), any())).thenReturn(true); + + mArchiveService = spy(new PackageArchiverService(mContext, pm)); + doReturn(ICON_PATH).when(mArchiveService).storeIcon(eq(PACKAGE), + any(LauncherActivityInfo.class), eq(mUserId)); } @Test @@ -175,15 +194,20 @@ public class PackageArchiverServiceTest { } @Test - public void archiveApp_packageNotInstalledForUser() { + public void archiveApp_packageNotInstalledForUser() throws IntentSender.SendIntentException { mPackageSetting.modifyUserState(UserHandle.CURRENT.getIdentifier()).setInstalled(false); - Exception e = assertThrows( - ParcelableException.class, - () -> mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, - UserHandle.CURRENT)); - assertThat(e.getCause()).isInstanceOf(PackageManager.NameNotFoundException.class); - assertThat(e.getCause()).hasMessageThat().isEqualTo( + mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT); + rule.mocks().getHandler().flush(); + + ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); + verify(mIntentSender).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any(), + any(), any()); + Intent value = intentCaptor.getValue(); + assertThat(value.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME)).isEqualTo(PACKAGE); + assertThat(value.getIntExtra(PackageInstaller.EXTRA_STATUS, 0)).isEqualTo( + PackageInstaller.STATUS_FAILURE); + assertThat(value.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)).isEqualTo( String.format("Package %s not found.", PACKAGE)); } @@ -223,13 +247,34 @@ public class PackageArchiverServiceTest { } @Test + public void archiveApp_storeIconFails() throws IntentSender.SendIntentException, IOException { + IOException e = new IOException("IO"); + doThrow(e).when(mArchiveService).storeIcon(eq(PACKAGE), + any(LauncherActivityInfo.class), eq(mUserId)); + + mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT); + rule.mocks().getHandler().flush(); + + ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); + verify(mIntentSender).sendIntent(any(), anyInt(), intentCaptor.capture(), any(), any(), + any(), any()); + Intent value = intentCaptor.getValue(); + assertThat(value.getStringExtra(PackageInstaller.EXTRA_PACKAGE_NAME)).isEqualTo(PACKAGE); + assertThat(value.getIntExtra(PackageInstaller.EXTRA_STATUS, 0)).isEqualTo( + PackageInstaller.STATUS_FAILURE); + assertThat(value.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE)).isEqualTo( + e.toString()); + } + + @Test public void archiveApp_success() { mArchiveService.requestArchive(PACKAGE, CALLER_PACKAGE, mIntentSender, UserHandle.CURRENT); + rule.mocks().getHandler().flush(); verify(mInstallerService).uninstall( eq(new VersionedPackage(PACKAGE, PackageManager.VERSION_CODE_HIGHEST)), eq(CALLER_PACKAGE), eq(DELETE_KEEP_DATA), eq(mIntentSender), - eq(UserHandle.CURRENT.getIdentifier())); + eq(UserHandle.CURRENT.getIdentifier()), anyInt()); assertThat(mPackageSetting.readUserState( UserHandle.CURRENT.getIdentifier()).getArchiveState()).isEqualTo( createArchiveState()); @@ -305,7 +350,7 @@ public class PackageArchiverServiceTest { mUserState.setArchiveState(createArchiveState()).setInstalled(false); mArchiveService.requestUnarchive(PACKAGE, CALLER_PACKAGE, UserHandle.CURRENT); - mMockSystem.mocks().getHandler().flush(); + rule.mocks().getHandler().flush(); ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); verify(mContext).sendOrderedBroadcastAsUser( @@ -331,20 +376,22 @@ public class PackageArchiverServiceTest { private static ArchiveState createArchiveState() { List<ArchiveState.ArchiveActivityInfo> activityInfos = new ArrayList<>(); for (LauncherActivityInfo mainActivity : createLauncherActivities()) { - // TODO(b/278553670) Extract and store launcher icons ArchiveState.ArchiveActivityInfo activityInfo = new ArchiveState.ArchiveActivityInfo( mainActivity.getLabel().toString(), - Path.of("/TODO"), null); + ICON_PATH, null); activityInfos.add(activityInfo); } return new ArchiveState(activityInfos, INSTALLER_PACKAGE); } private static List<LauncherActivityInfo> createLauncherActivities() { + ActivityInfo activityInfo = mock(ActivityInfo.class); LauncherActivityInfo activity1 = mock(LauncherActivityInfo.class); when(activity1.getLabel()).thenReturn("activity1"); + when(activity1.getActivityInfo()).thenReturn(activityInfo); LauncherActivityInfo activity2 = mock(LauncherActivityInfo.class); when(activity2.getLabel()).thenReturn("activity2"); + when(activity2.getActivityInfo()).thenReturn(activityInfo); return List.of(activity1, activity2); } diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java index 94fff22cffe1..a3917765e4b8 100644 --- a/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/tare/AgentTest.java @@ -55,6 +55,7 @@ public class AgentTest { @Mock private InternalResourceService mIrs; + private Agent mAgent; private Scribe mScribe; private static class MockScribe extends Scribe { @@ -80,10 +81,13 @@ public class AgentTest { doReturn(mIrs).when(mIrs).getLock(); doReturn(mock(AlarmManager.class)).when(mContext).getSystemService(Context.ALARM_SERVICE); mScribe = new MockScribe(mIrs, mAnalyst); + mAgent = new Agent(mIrs, mScribe, mAnalyst); } @After public void tearDown() { + mAgent.tearDownLocked(); + if (mMockingSession != null) { mMockingSession.finishMocking(); } @@ -99,7 +103,6 @@ public class AgentTest { final int userId = 0; final String pkgName = "com.test"; - final Agent agent = new Agent(mIrs, mScribe, mAnalyst); final Ledger ledger = mScribe.getLedgerLocked(userId, pkgName); doReturn(consumptionLimit).when(mIrs).getConsumptionLimitLocked(); @@ -107,66 +110,64 @@ public class AgentTest { .getMaxSatiatedBalance(anyInt(), anyString()); Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5, 10); - agent.recordTransactionLocked(userId, pkgName, ledger, transaction, false); + mAgent.recordTransactionLocked(userId, pkgName, ledger, transaction, false); assertEquals(5, ledger.getCurrentBalance()); assertEquals(remainingCakes - 10, mScribe.getRemainingConsumableCakesLocked()); - agent.onPackageRemovedLocked(userId, pkgName); + mAgent.onPackageRemovedLocked(userId, pkgName); assertEquals(remainingCakes - 10, mScribe.getRemainingConsumableCakesLocked()); assertLedgersEqual(new Ledger(), mScribe.getLedgerLocked(userId, pkgName)); } @Test public void testRecordTransaction_UnderMax() { - Agent agent = new Agent(mIrs, mScribe, mAnalyst); Ledger ledger = new Ledger(); doReturn(1_000_000L).when(mIrs).getConsumptionLimitLocked(); doReturn(1_000_000L).when(mEconomicPolicy).getMaxSatiatedBalance(anyInt(), anyString()); Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5, 0); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(5, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 995, 0); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -500, 250); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(500, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 999_500L, 500); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1_000_000L, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -1_000_001L, 1000); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(-1, ledger.getCurrentBalance()); } @Test public void testRecordTransaction_MaxConsumptionLimit() { - Agent agent = new Agent(mIrs, mScribe, mAnalyst); Ledger ledger = new Ledger(); doReturn(1000L).when(mIrs).getConsumptionLimitLocked(); doReturn(1_000_000L).when(mEconomicPolicy).getMaxSatiatedBalance(anyInt(), anyString()); Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5, 0); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(5, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 995, 0); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -500, 250); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(500, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 2000, 0); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(2500, ledger.getCurrentBalance()); // ConsumptionLimit can change as the battery level changes. Ledger balances shouldn't be @@ -174,57 +175,56 @@ public class AgentTest { doReturn(900L).when(mIrs).getConsumptionLimitLocked(); transaction = new Ledger.Transaction(0, 0, 0, null, 100, 0); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(2600, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -50, 50); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(2550, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -200, 100); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(2350, ledger.getCurrentBalance()); doReturn(800L).when(mIrs).getConsumptionLimitLocked(); transaction = new Ledger.Transaction(0, 0, 0, null, 100, 0); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(2450, ledger.getCurrentBalance()); } @Test public void testRecordTransaction_MaxSatiatedBalance() { - Agent agent = new Agent(mIrs, mScribe, mAnalyst); Ledger ledger = new Ledger(); doReturn(1_000_000L).when(mIrs).getConsumptionLimitLocked(); doReturn(1000L).when(mEconomicPolicy).getMaxSatiatedBalance(anyInt(), anyString()); Ledger.Transaction transaction = new Ledger.Transaction(0, 0, 0, null, 5, 0); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(5, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 995, 0); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -500, 250); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(500, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, 999_500L, 1000); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1_000, ledger.getCurrentBalance()); // Shouldn't change in normal operation, but adding test case in case it does. doReturn(900L).when(mEconomicPolicy).getMaxSatiatedBalance(anyInt(), anyString()); transaction = new Ledger.Transaction(0, 0, 0, null, 500, 0); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(1_000, ledger.getCurrentBalance()); transaction = new Ledger.Transaction(0, 0, 0, null, -1001, 500); - agent.recordTransactionLocked(0, "com.test", ledger, transaction, false); + mAgent.recordTransactionLocked(0, "com.test", ledger, transaction, false); assertEquals(-1, ledger.getCurrentBalance()); } } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java index 6c7b995d07a2..035bef6b8feb 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/ProxyManagerTest.java @@ -23,7 +23,14 @@ import static com.android.server.accessibility.ProxyAccessibilityServiceConnecti import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_CLASS_NAME; import static com.android.server.accessibility.ProxyManager.PROXY_COMPONENT_PACKAGE_NAME; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.accessibilityservice.AccessibilityGestureEvent; import android.accessibilityservice.AccessibilityServiceInfo; @@ -40,6 +47,7 @@ import android.graphics.Region; import android.os.IBinder; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.platform.test.flag.junit.SetFlagsRule; import android.util.ArraySet; import android.view.KeyEvent; import android.view.MotionEvent; @@ -48,6 +56,8 @@ import android.view.accessibility.AccessibilityManager; import android.view.accessibility.IAccessibilityManagerClient; import android.view.inputmethod.EditorInfo; +import androidx.test.InstrumentationRegistry; + import com.android.internal.R; import com.android.internal.inputmethod.IAccessibilityInputMethodSession; import com.android.internal.inputmethod.IAccessibilityInputMethodSessionCallback; @@ -58,20 +68,12 @@ import com.android.server.accessibility.test.MessageCapturingHandler; import com.android.server.companion.virtual.VirtualDeviceManagerInternal; import com.android.server.wm.WindowManagerInternal; -import static com.google.common.truth.Truth.assertThat; - -import androidx.test.InstrumentationRegistry; - -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import org.junit.After; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import java.util.ArrayList; @@ -87,6 +89,10 @@ public class ProxyManagerTest { private static final int DEVICE_ID = 10; private static final int STREAMED_CALLING_UID = 9876; + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + + @Mock private Context mMockContext; @Mock private AccessibilitySecurityPolicy mMockSecurityPolicy; @Mock private AccessibilityWindowManager mMockA11yWindowManager; @@ -110,6 +116,8 @@ public class ProxyManagerTest { MockitoAnnotations.initMocks(this); final Resources resources = InstrumentationRegistry.getContext().getResources(); + mSetFlagsRule.enableFlags(Flags.FLAG_PROXY_USE_APPS_ON_VIRTUAL_DEVICE_LISTENER); + mFocusStrokeWidthDefaultValue = resources.getDimensionPixelSize(R.dimen.accessibility_focus_highlight_stroke_width); mFocusColorDefaultValue = resources.getColor(R.color.accessibility_focus_highlight_color); @@ -218,6 +226,39 @@ public class ProxyManagerTest { } /** + * Tests that the manager's AppsOnVirtualDeviceListener implementation propagates the running + * app changes to the proxy device. + */ + @Test + public void testUpdateProxyOfRunningAppsChange_changedUidIsStreamedApp_propagatesChange() { + final VirtualDeviceManagerInternal localVdm = + Mockito.mock(VirtualDeviceManagerInternal.class); + when(localVdm.getDeviceIdsForUid(anyInt())).thenReturn(new ArraySet(Set.of(DEVICE_ID))); + + mProxyManager.setLocalVirtualDeviceManager(localVdm); + registerProxy(DISPLAY_ID); + verify(localVdm).registerAppsOnVirtualDeviceListener(any()); + + final ArraySet<Integer> runningUids = new ArraySet(Set.of(STREAMED_CALLING_UID)); + + // Flush any existing messages. The messages after this come from onProxyChanged. + mMessageCapturingHandler.sendAllMessages(); + + // The virtual device has been updated with the streamed app's UID, so the proxy is + // updated. + mProxyManager.notifyProxyOfRunningAppsChange(runningUids); + + verify(localVdm).getDeviceIdsForUid(STREAMED_CALLING_UID); + verify(mMockProxySystemSupport).getCurrentUserClientsLocked(); + verify(mMockProxySystemSupport).getGlobalClientsLocked(); + // Messages to notify IAccessibilityManagerClients should be posted. + assertThat(mMessageCapturingHandler.hasMessages()).isTrue(); + + mProxyManager.unregisterProxy(DISPLAY_ID); + verify(localVdm).unregisterAppsOnVirtualDeviceListener(any()); + } + + /** * Tests that getting the first device id for an app uid, such as when an app queries for * device-specific state, returns the right device id. */ diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java index 0b730f139f3e..fa6e7f60c1b0 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthenticationStatsCollectorTest.java @@ -115,6 +115,11 @@ public class AuthenticationStatsCollectorTest { // Assert that the user doesn't exist in the map initially. assertThat(mAuthenticationStatsCollector.getAuthenticationStatsForUser(USER_ID_1)).isNull(); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) + .thenReturn(true); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true); + when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true); + mAuthenticationStatsCollector.authenticate(USER_ID_1, true /* authenticated */); AuthenticationStats authenticationStats = @@ -130,6 +135,11 @@ public class AuthenticationStatsCollectorTest { // Assert that the user doesn't exist in the map initially. assertThat(mAuthenticationStatsCollector.getAuthenticationStatsForUser(USER_ID_1)).isNull(); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) + .thenReturn(true); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true); + when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true); + mAuthenticationStatsCollector.authenticate(USER_ID_1, false /* authenticated */); AuthenticationStats authenticationStats = @@ -176,6 +186,11 @@ public class AuthenticationStatsCollectorTest { 40 /* rejectedAttempts */, 0 /* enrollmentNotifications */, 0 /* modality */)); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) + .thenReturn(true); + when(mPackageManager.hasSystemFeature(PackageManager.FEATURE_FACE)).thenReturn(true); + when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true); + mAuthenticationStatsCollector.authenticate(USER_ID_1, false /* authenticated */); // Assert that no notification should be sent. @@ -233,13 +248,13 @@ public class AuthenticationStatsCollectorTest { // Assert that no notification should be sent. verify(mBiometricNotification, never()).sendFaceEnrollNotification(any()); verify(mBiometricNotification, never()).sendFpEnrollNotification(any()); - // Assert that data has been reset. + // Assert that data hasn't been reset. AuthenticationStats authenticationStats = mAuthenticationStatsCollector .getAuthenticationStatsForUser(USER_ID_1); - assertThat(authenticationStats.getTotalAttempts()).isEqualTo(0); - assertThat(authenticationStats.getRejectedAttempts()).isEqualTo(0); + assertThat(authenticationStats.getTotalAttempts()).isEqualTo(500); + assertThat(authenticationStats.getRejectedAttempts()).isEqualTo(400); assertThat(authenticationStats.getEnrollmentNotifications()).isEqualTo(0); - assertThat(authenticationStats.getFrr()).isWithin(0f).of(-1.0f); + assertThat(authenticationStats.getFrr()).isWithin(0f).of(0.8f); } @Test @@ -260,13 +275,13 @@ public class AuthenticationStatsCollectorTest { // Assert that no notification should be sent. verify(mBiometricNotification, never()).sendFaceEnrollNotification(any()); verify(mBiometricNotification, never()).sendFpEnrollNotification(any()); - // Assert that data has been reset. + // Assert that data hasn't been reset. AuthenticationStats authenticationStats = mAuthenticationStatsCollector .getAuthenticationStatsForUser(USER_ID_1); - assertThat(authenticationStats.getTotalAttempts()).isEqualTo(0); - assertThat(authenticationStats.getRejectedAttempts()).isEqualTo(0); + assertThat(authenticationStats.getTotalAttempts()).isEqualTo(500); + assertThat(authenticationStats.getRejectedAttempts()).isEqualTo(400); assertThat(authenticationStats.getEnrollmentNotifications()).isEqualTo(0); - assertThat(authenticationStats.getFrr()).isWithin(0f).of(-1.0f); + assertThat(authenticationStats.getFrr()).isWithin(0f).of(0.8f); } @Test diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java index b22798e6eaed..5dfce0613190 100644 --- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java @@ -326,24 +326,6 @@ public final class UserManagerTest { assertThat(hasUser(user2.id)).isTrue(); } - - @MediumTest - @Test - public void testGetFullUserCount() throws Exception { - assertThat(mUserManager.getFullUserCount()).isEqualTo(1); - UserInfo user1 = createUser("User 1", UserInfo.FLAG_FULL); - UserInfo user2 = createUser("User 2", UserInfo.FLAG_ADMIN); - - assertThat(user1).isNotNull(); - assertThat(user2).isNotNull(); - - assertThat(mUserManager.getFullUserCount()).isEqualTo(3); - removeUser(user1.id); - assertThat(mUserManager.getFullUserCount()).isEqualTo(2); - removeUser(user2.id); - assertThat(mUserManager.getFullUserCount()).isEqualTo(1); - } - /** * Tests that UserManager knows how many users can be created. * diff --git a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java index c25f0cb91caa..0eec9cd93f3b 100644 --- a/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java +++ b/services/tests/vibrator/src/com/android/server/vibrator/VibratorManagerServiceTest.java @@ -89,6 +89,7 @@ import android.view.HapticFeedbackConstants; import android.view.InputDevice; import androidx.test.InstrumentationRegistry; +import androidx.test.filters.FlakyTest; import com.android.internal.app.IBatteryStats; import com.android.internal.util.FrameworkStatsLog; @@ -834,6 +835,7 @@ public class VibratorManagerServiceTest { eq(AudioAttributes.USAGE_UNKNOWN), anyInt(), anyString()); } + @FlakyTest @Test public void vibrate_withOngoingRepeatingVibration_ignoresEffect() throws Exception { mockVibrators(1); @@ -920,6 +922,7 @@ public class VibratorManagerServiceTest { cancelVibrate(service); // Clean up repeating effect. } + @FlakyTest @Test public void vibrate_withNewSameImportanceVibrationButOngoingIsRepeating_ignoreNewVibration() throws Exception { @@ -973,6 +976,7 @@ public class VibratorManagerServiceTest { cancelVibrate(service); // Clean up repeating effect. } + @FlakyTest @Test public void vibrate_withNewUnknownUsageVibrationAndNotRepeating_ignoreNewVibration() throws Exception { @@ -1764,6 +1768,7 @@ public class VibratorManagerServiceTest { cancelVibrate(service); // Clean up long effect. } + @FlakyTest @Test public void onExternalVibration_withNewSameImportanceButRepeating_cancelsOngoingVibration() throws Exception { diff --git a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java index c84eab3a6660..622e81eab611 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ContentRecorderTests.java @@ -16,6 +16,8 @@ package com.android.server.wm; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR; +import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; @@ -77,6 +79,7 @@ import java.util.concurrent.CountDownLatch; @RunWith(WindowTestRunner.class) public class ContentRecorderTests extends WindowTestsBase { private static IBinder sTaskWindowContainerToken; + private DisplayContent mVirtualDisplayContent; private Task mTask; private final ContentRecordingSession mDisplaySession = ContentRecordingSession.createDisplaySession(DEFAULT_DISPLAY); @@ -107,11 +110,11 @@ public class ContentRecorderTests extends WindowTestsBase { displayInfo.logicalWidth = sSurfaceSize.x; displayInfo.logicalHeight = sSurfaceSize.y; displayInfo.state = STATE_ON; - final DisplayContent virtualDisplayContent = createNewDisplay(displayInfo); - final int displayId = virtualDisplayContent.getDisplayId(); - mContentRecorder = new ContentRecorder(virtualDisplayContent, + mVirtualDisplayContent = createNewDisplay(displayInfo); + final int displayId = mVirtualDisplayContent.getDisplayId(); + mContentRecorder = new ContentRecorder(mVirtualDisplayContent, mMediaProjectionManagerWrapper); - spyOn(virtualDisplayContent); + spyOn(mVirtualDisplayContent); // GIVEN MediaProjection has already initialized the WindowToken of the DisplayArea to // record. @@ -119,7 +122,7 @@ public class ContentRecorderTests extends WindowTestsBase { mDisplaySession.setDisplayToRecord(mDefaultDisplay.mDisplayId); // GIVEN there is a window token associated with a task to record. - sTaskWindowContainerToken = setUpTaskWindowContainerToken(virtualDisplayContent); + sTaskWindowContainerToken = setUpTaskWindowContainerToken(mVirtualDisplayContent); mTaskSession = ContentRecordingSession.createTaskSession(sTaskWindowContainerToken); mTaskSession.setVirtualDisplayId(displayId); @@ -252,7 +255,11 @@ public class ContentRecorderTests extends WindowTestsBase { public void testOnConfigurationChanged_resizesSurface() { mContentRecorder.setContentRecordingSession(mDisplaySession); mContentRecorder.updateRecording(); - mContentRecorder.onConfigurationChanged(ORIENTATION_PORTRAIT); + // Ensure a different orientation when we check if something has changed. + @Configuration.Orientation final int lastOrientation = + mDisplayContent.getConfiguration().orientation == ORIENTATION_PORTRAIT + ? ORIENTATION_LANDSCAPE : ORIENTATION_PORTRAIT; + mContentRecorder.onConfigurationChanged(lastOrientation); verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(), anyFloat()); @@ -261,12 +268,53 @@ public class ContentRecorderTests extends WindowTestsBase { } @Test + public void testOnConfigurationChanged_resizesVirtualDisplay() { + final int newWidth = 55; + mContentRecorder.setContentRecordingSession(mDisplaySession); + mContentRecorder.updateRecording(); + + // The user rotates the device, so the host app resizes the virtual display for the capture. + resizeDisplay(mDisplayContent, newWidth, sSurfaceSize.y); + resizeDisplay(mVirtualDisplayContent, newWidth, sSurfaceSize.y); + mContentRecorder.onConfigurationChanged(mDisplayContent.getConfiguration().orientation); + + verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(), + anyFloat()); + verify(mTransaction, atLeast(2)).setMatrix(eq(mRecordedSurface), anyFloat(), anyFloat(), + anyFloat(), anyFloat()); + } + + @Test + public void testOnConfigurationChanged_rotateVirtualDisplay() { + mContentRecorder.setContentRecordingSession(mDisplaySession); + mContentRecorder.updateRecording(); + + // Change a value that we shouldn't rely upon; it has the wrong type. + mVirtualDisplayContent.setOverrideOrientation(SCREEN_ORIENTATION_FULL_SENSOR); + mContentRecorder.onConfigurationChanged( + mVirtualDisplayContent.getConfiguration().orientation); + + // No resize is issued, only the initial transformations when we started recording. + verify(mTransaction).setPosition(eq(mRecordedSurface), anyFloat(), + anyFloat()); + verify(mTransaction).setMatrix(eq(mRecordedSurface), anyFloat(), anyFloat(), + anyFloat(), anyFloat()); + } + + @Test public void testOnTaskOrientationConfigurationChanged_resizesSurface() { mContentRecorder.setContentRecordingSession(mTaskSession); mContentRecorder.updateRecording(); Configuration config = mTask.getConfiguration(); - config.orientation = ORIENTATION_PORTRAIT; + // Ensure a different orientation when we compare. + @Configuration.Orientation final int orientation = + config.orientation == ORIENTATION_PORTRAIT ? ORIENTATION_LANDSCAPE + : ORIENTATION_PORTRAIT; + final Rect lastBounds = config.windowConfiguration.getBounds(); + config.orientation = orientation; + config.windowConfiguration.setBounds( + new Rect(0, 0, lastBounds.height(), lastBounds.width())); mTask.onConfigurationChanged(config); verify(mTransaction, atLeast(2)).setPosition(eq(mRecordedSurface), anyFloat(), @@ -279,13 +327,15 @@ public class ContentRecorderTests extends WindowTestsBase { public void testOnTaskBoundsConfigurationChanged_notifiesCallback() { mTask.getRootTask().setWindowingMode(WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW); + final int minWidth = 222; + final int minHeight = 777; final int recordedWidth = 333; final int recordedHeight = 999; final ActivityInfo info = new ActivityInfo(); info.windowLayout = new ActivityInfo.WindowLayout(-1 /* width */, -1 /* widthFraction */, -1 /* height */, -1 /* heightFraction */, - Gravity.NO_GRAVITY, recordedWidth, recordedHeight); + Gravity.NO_GRAVITY, minWidth, minHeight); mTask.setMinDimensions(info); // WHEN a recording is ongoing. diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java index 994dcf1e2ea5..411712e6b577 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java @@ -23,8 +23,6 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.view.WindowInsets.Type.navigationBars; import static android.view.WindowInsets.Type.statusBars; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; @@ -108,7 +106,7 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testControlsForDispatch_forceStatusBarVisible() { - addStatusBar().mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; + addStatusBar().mAttrs.forciblyShownTypes |= statusBars(); addNavigationBar(); final InsetsSourceControl[] controls = addAppWindowAndGetControlsForDispatch(); @@ -120,8 +118,8 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testControlsForDispatch_statusBarForceShowNavigation() { - addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade").mAttrs.privateFlags |= - PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; + addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade").mAttrs.forciblyShownTypes |= + navigationBars(); addStatusBar(); addNavigationBar(); @@ -135,7 +133,7 @@ public class InsetsPolicyTest extends WindowTestsBase { @Test public void testControlsForDispatch_statusBarForceShowNavigation_butFocusedAnyways() { WindowState notifShade = addWindow(TYPE_NOTIFICATION_SHADE, "notificationShade"); - notifShade.mAttrs.privateFlags |= PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION; + notifShade.mAttrs.forciblyShownTypes |= navigationBars(); addNavigationBar(); mDisplayContent.getInsetsPolicy().updateBarControlTarget(notifShade); diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 0cdd9b8a9e0b..8f68c0fa0b73 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -112,6 +112,7 @@ import android.view.InsetsState; import android.view.WindowInsets; import android.view.WindowManager; +import androidx.test.filters.FlakyTest; import androidx.test.filters.MediumTest; import com.android.internal.policy.SystemBarUtils; @@ -2361,6 +2362,7 @@ public class SizeCompatTests extends WindowTestsBase { } @Test + @FlakyTest(bugId = 299220009) public void testUserOverrideAspectRatioNotEnabled() { setUpDisplaySizeWithApp(/* dw */ 1600, /* dh */ 1400); @@ -2409,8 +2411,9 @@ public class SizeCompatTests extends WindowTestsBase { .setUid(android.os.Process.myUid()) .build(); activity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); - activity.mWmService.mLetterboxConfiguration - .setUserAppAspectRatioSettingsOverrideEnabled(enabled); + spyOn(activity.mWmService.mLetterboxConfiguration); + doReturn(enabled).when(activity.mWmService.mLetterboxConfiguration) + .isUserAppAspectRatioSettingsEnabled(); // Set user aspect ratio override final IPackageManager pm = mAtm.getPackageManager(); try { @@ -4249,6 +4252,7 @@ public class SizeCompatTests extends WindowTestsBase { // Set up a display in landscape with a fixed-orientation PORTRAIT app setUpDisplaySizeWithApp(2800, 1400); mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + mWm.mLetterboxConfiguration.setIsAutomaticReachabilityInBookModeEnabled(false); mWm.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(0.5f); prepareUnresizable(mActivity, 1.75f, SCREEN_ORIENTATION_PORTRAIT); diff --git a/tools/aapt2/format/Archive_test.cpp b/tools/aapt2/format/Archive_test.cpp index 3c44da710d94..fd50af92ceee 100644 --- a/tools/aapt2/format/Archive_test.cpp +++ b/tools/aapt2/format/Archive_test.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include <stdlib.h> + #include "test/Test.h" namespace aapt { @@ -34,6 +36,29 @@ class TestData : public io::MallocData { std::string error_; }; +class TzSetter { + public: + explicit TzSetter(const std::string& new_tz) { + old_tz_ = getenv("TZ"); + new_tz_ = "TZ=" + new_tz; + putenv(const_cast<char*>(new_tz_.c_str())); + tzset(); + } + + ~TzSetter() { + if (old_tz_) { + putenv(old_tz_); + } else { + putenv(const_cast<char*>("TZ")); + } + tzset(); + } + + private: + char* old_tz_; + std::string new_tz_; +}; + std::unique_ptr<uint8_t[]> MakeTestArray() { auto array = std::make_unique<uint8_t[]>(kTestDataLength); for (int index = 0; index < kTestDataLength; ++index) { @@ -86,6 +111,22 @@ void VerifyZipFile(const std::string& output_path, const std::string& file, cons } } +void VerifyZipFileTimestamps(const std::string& output_path) { + std::unique_ptr<io::ZipFileCollection> zip = io::ZipFileCollection::Create(output_path, nullptr); + auto it = zip->Iterator(); + while (it->HasNext()) { + auto file = it->Next(); + struct tm modification_time; + ASSERT_TRUE(file->GetModificationTime(&modification_time)); + EXPECT_EQ(modification_time.tm_year, 80); + EXPECT_EQ(modification_time.tm_mon, 0); + EXPECT_EQ(modification_time.tm_mday, 1); + EXPECT_EQ(modification_time.tm_hour, 0); + EXPECT_EQ(modification_time.tm_min, 0); + EXPECT_EQ(modification_time.tm_sec, 0); + } +} + TEST_F(ArchiveTest, DirectoryWriteEntrySuccess) { std::string output_path = GetTestPath("output"); std::unique_ptr<IArchiveWriter> writer = MakeDirectoryWriter(output_path); @@ -206,4 +247,73 @@ TEST_F(ArchiveTest, ZipFileWriteFileError) { ASSERT_EQ("ZipFileWriteFileError", writer->GetError()); } +TEST_F(ArchiveTest, ZipFileTimeZoneUTC) { + TzSetter tz("UTC0"); + std::string output_path = GetTestPath("output.apk"); + std::unique_ptr<IArchiveWriter> writer = MakeZipFileWriter(output_path); + std::unique_ptr<uint8_t[]> data1 = MakeTestArray(); + std::unique_ptr<uint8_t[]> data2 = MakeTestArray(); + + ASSERT_TRUE(writer->StartEntry("test1", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data1.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + ASSERT_TRUE(writer->StartEntry("test2", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data2.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + writer.reset(); + + // All zip file entries must have the same timestamp, regardless of time zone. See: b/277978832 + VerifyZipFileTimestamps(output_path); +} + +TEST_F(ArchiveTest, ZipFileTimeZoneWestOfUTC) { + TzSetter tz("PST8"); + std::string output_path = GetTestPath("output.apk"); + std::unique_ptr<IArchiveWriter> writer = MakeZipFileWriter(output_path); + std::unique_ptr<uint8_t[]> data1 = MakeTestArray(); + std::unique_ptr<uint8_t[]> data2 = MakeTestArray(); + + ASSERT_TRUE(writer->StartEntry("test1", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data1.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + ASSERT_TRUE(writer->StartEntry("test2", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data2.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + writer.reset(); + + // All zip file entries must have the same timestamp, regardless of time zone. See: b/277978832 + VerifyZipFileTimestamps(output_path); +} + +TEST_F(ArchiveTest, ZipFileTimeZoneEastOfUTC) { + TzSetter tz("EET-2"); + std::string output_path = GetTestPath("output.apk"); + std::unique_ptr<IArchiveWriter> writer = MakeZipFileWriter(output_path); + std::unique_ptr<uint8_t[]> data1 = MakeTestArray(); + std::unique_ptr<uint8_t[]> data2 = MakeTestArray(); + + ASSERT_TRUE(writer->StartEntry("test1", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data1.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + ASSERT_TRUE(writer->StartEntry("test2", 0)); + ASSERT_TRUE(writer->Write(static_cast<const void*>(data2.get()), kTestDataLength)); + ASSERT_TRUE(writer->FinishEntry()); + ASSERT_FALSE(writer->HadError()); + + writer.reset(); + + // All zip file entries must have the same timestamp, regardless of time zone. See: b/277978832 + VerifyZipFileTimestamps(output_path); +} + } // namespace aapt diff --git a/tools/aapt2/io/File.h b/tools/aapt2/io/File.h index 08d497def8a4..673d1b75e660 100644 --- a/tools/aapt2/io/File.h +++ b/tools/aapt2/io/File.h @@ -57,6 +57,11 @@ class IFile { return false; } + // Fills in buf with the last modification time of the file. Returns true if successful, + // otherwise false (i.e., the operation is not supported or the file system is unable to provide + // a last modification time). + virtual bool GetModificationTime(struct tm* buf) const = 0; + private: // Any segments created from this IFile need to be owned by this IFile, so // keep them @@ -79,6 +84,10 @@ class FileSegment : public IFile { return file_->GetSource(); } + bool GetModificationTime(struct tm* buf) const override { + return file_->GetModificationTime(buf); + }; + private: DISALLOW_COPY_AND_ASSIGN(FileSegment); diff --git a/tools/aapt2/io/FileSystem.cpp b/tools/aapt2/io/FileSystem.cpp index a64982a7fa5c..6a692e497816 100644 --- a/tools/aapt2/io/FileSystem.cpp +++ b/tools/aapt2/io/FileSystem.cpp @@ -14,9 +14,12 @@ * limitations under the License. */ +#define _POSIX_THREAD_SAFE_FUNCTIONS // For mingw localtime_r(). + #include "io/FileSystem.h" #include <dirent.h> +#include <sys/stat.h> #include "android-base/errors.h" #include "androidfw/Source.h" @@ -54,6 +57,23 @@ const android::Source& RegularFile::GetSource() const { return source_; } +bool RegularFile::GetModificationTime(struct tm* buf) const { + if (buf == nullptr) { + return false; + } + struct stat stat_buf; + if (stat(source_.path.c_str(), &stat_buf) != 0) { + return false; + } + + struct tm* ptm; + struct tm tm_result; + ptm = localtime_r(&stat_buf.st_mtime, &tm_result); + + *buf = *ptm; + return true; +} + FileCollectionIterator::FileCollectionIterator(FileCollection* collection) : current_(collection->files_.begin()), end_(collection->files_.end()) {} diff --git a/tools/aapt2/io/FileSystem.h b/tools/aapt2/io/FileSystem.h index 0e798fc1b975..f975196b9cfa 100644 --- a/tools/aapt2/io/FileSystem.h +++ b/tools/aapt2/io/FileSystem.h @@ -32,6 +32,7 @@ class RegularFile : public IFile { std::unique_ptr<IData> OpenAsData() override; std::unique_ptr<io::InputStream> OpenInputStream() override; const android::Source& GetSource() const override; + bool GetModificationTime(struct tm* buf) const override; private: DISALLOW_COPY_AND_ASSIGN(RegularFile); diff --git a/tools/aapt2/io/ZipArchive.cpp b/tools/aapt2/io/ZipArchive.cpp index 4a5385d90d3b..cb5bbe96b8b7 100644 --- a/tools/aapt2/io/ZipArchive.cpp +++ b/tools/aapt2/io/ZipArchive.cpp @@ -75,6 +75,14 @@ bool ZipFile::WasCompressed() { return zip_entry_.method != kCompressStored; } +bool ZipFile::GetModificationTime(struct tm* buf) const { + if (buf == nullptr) { + return false; + } + *buf = zip_entry_.GetModificationTime(); + return true; +} + ZipFileCollectionIterator::ZipFileCollectionIterator( ZipFileCollection* collection) : current_(collection->files_.begin()), end_(collection->files_.end()) {} diff --git a/tools/aapt2/io/ZipArchive.h b/tools/aapt2/io/ZipArchive.h index c263aa490d22..ac125d097983 100644 --- a/tools/aapt2/io/ZipArchive.h +++ b/tools/aapt2/io/ZipArchive.h @@ -38,6 +38,7 @@ class ZipFile : public IFile { std::unique_ptr<io::InputStream> OpenInputStream() override; const android::Source& GetSource() const override; bool WasCompressed() override; + bool GetModificationTime(struct tm* buf) const override; private: ::ZipArchiveHandle zip_handle_; diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h index 83a0f3f3f652..e48668cf96a3 100644 --- a/tools/aapt2/test/Common.h +++ b/tools/aapt2/test/Common.h @@ -98,6 +98,10 @@ class TestFile : public io::IFile { return source_; } + bool GetModificationTime(struct tm* buf) const override { + return false; + }; + private: DISALLOW_COPY_AND_ASSIGN(TestFile); diff --git a/tools/lint/common/Android.bp b/tools/lint/common/Android.bp index 898f88b8759c..8bfbfe5f60b3 100644 --- a/tools/lint/common/Android.bp +++ b/tools/lint/common/Android.bp @@ -27,3 +27,30 @@ java_library_host { libs: ["lint_api"], kotlincflags: ["-Xjvm-default=all"], } + +java_defaults { + name: "AndroidLintCheckerTestDefaults", + srcs: ["checks/src/test/java/**/*.kt"], + static_libs: [ + "junit", + "lint", + "lint_tests", + ], + test_options: { + unit_test: true, + tradefed_options: [ + { + // lint bundles in some classes that were built with older versions + // of libraries, and no longer load. Since tradefed tries to load + // all classes in the jar to look for tests, it crashes loading them. + // Exclude these classes from tradefed's search. + name: "exclude-paths", + value: "org/apache", + }, + { + name: "exclude-paths", + value: "META-INF", + }, + ], + }, +} diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt b/tools/lint/common/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt index ab6d871d6ea6..ab6d871d6ea6 100644 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt +++ b/tools/lint/common/src/main/java/com/google/android/lint/aidl/AidlImplementationDetector.kt diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt b/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt index f1727b78f135..a18ed1555998 100644 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/Constants.kt +++ b/tools/lint/common/src/main/java/com/google/android/lint/aidl/Constants.kt @@ -29,9 +29,10 @@ val AIDL_PERMISSION_ANNOTATIONS = listOf( const val BINDER_CLASS = "android.os.Binder" const val IINTERFACE_INTERFACE = "android.os.IInterface" -const val AIDL_PERMISSION_HELPER_SUFFIX = "_enforcePermission" const val PERMISSION_PREFIX_LITERAL = "android.permission." +const val AIDL_PERMISSION_HELPER_SUFFIX = "_enforcePermission" + /** * If a non java (e.g. c++) backend is enabled, the @EnforcePermission * annotation cannot be used. At time of writing, the mechanism diff --git a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt b/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt index d41fee3fc0dc..d41fee3fc0dc 100644 --- a/tools/lint/global/checks/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt +++ b/tools/lint/common/src/main/java/com/google/android/lint/aidl/EnforcePermissionUtils.kt diff --git a/tools/lint/fix/soong_lint_fix.py b/tools/lint/fix/soong_lint_fix.py index cd4d778d1dec..acc0ad043171 100644 --- a/tools/lint/fix/soong_lint_fix.py +++ b/tools/lint/fix/soong_lint_fix.py @@ -29,6 +29,39 @@ PATH_PREFIX = "out/soong/.intermediates" PATH_SUFFIX = "android_common/lint" FIX_ZIP = "suggested-fixes.zip" + +class SoongModule: + """A Soong module to lint. + + The constructor takes the name of the module (for example, + "framework-minus-apex"). find() must be called to extract the intermediate + module path from Soong's module-info.json + """ + def __init__(self, name): + self._name = name + + def find(self, module_info): + """Finds the module in the loaded module_info.json.""" + if self._name not in module_info: + raise Exception(f"Module {self._name} not found!") + + partial_path = module_info[self._name]["path"][0] + print(f"Found module {partial_path}/{self._name}.") + self._path = f"{PATH_PREFIX}/{partial_path}/{self._name}/{PATH_SUFFIX}" + + @property + def name(self): + return self._name + + @property + def lint_report(self): + return f"{self._path}/lint-report.txt" + + @property + def suggested_fixes(self): + return f"{self._path}/{FIX_ZIP}" + + class SoongLintFix: """ This class creates a command line tool that will @@ -53,16 +86,14 @@ class SoongLintFix: self._parser = _setup_parser() self._args = None self._kwargs = None - self._path = None - self._target = None - + self._modules = [] - def run(self, additional_setup=None, custom_fix=None): + def run(self): """ Run the script """ self._setup() - self._find_module() + self._find_modules() self._lint() if not self._args.no_fix: @@ -87,8 +118,6 @@ class SoongLintFix: os.chdir(ANDROID_BUILD_TOP) - - def _find_module(self): print("Refreshing soong modules...") try: os.mkdir(ANDROID_PRODUCT_OUT) @@ -97,48 +126,47 @@ class SoongLintFix: subprocess.call(f"{SOONG_UI} --make-mode {PRODUCT_OUT}/module-info.json", **self._kwargs) print("done.") + + def _find_modules(self): with open(f"{ANDROID_PRODUCT_OUT}/module-info.json") as f: module_info = json.load(f) - if self._args.module not in module_info: - sys.exit(f"Module {self._args.module} not found!") - - module_path = module_info[self._args.module]["path"][0] - print(f"Found module {module_path}/{self._args.module}.") - - self._path = f"{PATH_PREFIX}/{module_path}/{self._args.module}/{PATH_SUFFIX}" - self._target = f"{self._path}/lint-report.txt" - + for module_name in self._args.modules: + module = SoongModule(module_name) + module.find(module_info) + self._modules.append(module) def _lint(self): print("Cleaning up any old lint results...") - try: - os.remove(f"{self._target}") - os.remove(f"{self._path}/{FIX_ZIP}") - except FileNotFoundError: - pass + for module in self._modules: + try: + os.remove(f"{module.lint_report}") + os.remove(f"{module.suggested_fixes}") + except FileNotFoundError: + pass print("done.") - print(f"Generating {self._target}") - subprocess.call(f"{SOONG_UI} --make-mode {self._target}", **self._kwargs) + target = " ".join([ module.lint_report for module in self._modules ]) + print(f"Generating {target}") + subprocess.call(f"{SOONG_UI} --make-mode {target}", **self._kwargs) print("done.") - def _fix(self): - print("Copying suggested fixes to the tree...") - with zipfile.ZipFile(f"{self._path}/{FIX_ZIP}") as zip: - for name in zip.namelist(): - if name.startswith("out") or not name.endswith(".java"): - continue - with zip.open(name) as src, open(f"{ANDROID_BUILD_TOP}/{name}", "wb") as dst: - shutil.copyfileobj(src, dst) + for module in self._modules: + print(f"Copying suggested fixes for {module.name} to the tree...") + with zipfile.ZipFile(f"{module.suggested_fixes}") as zip: + for name in zip.namelist(): + if name.startswith("out") or not name.endswith(".java"): + continue + with zip.open(name) as src, open(f"{ANDROID_BUILD_TOP}/{name}", "wb") as dst: + shutil.copyfileobj(src, dst) print("done.") - def _print(self): - print("### lint-report.txt ###", end="\n\n") - with open(self._target, "r") as f: - print(f.read()) + for module in self._modules: + print(f"### lint-report.txt {module.name} ###", end="\n\n") + with open(module.lint_report, "r") as f: + print(f.read()) def _setup_parser(): @@ -151,7 +179,8 @@ def _setup_parser(): **Gotcha**: You must have run `source build/envsetup.sh` and `lunch` first. """, formatter_class=argparse.RawTextHelpFormatter) - parser.add_argument('module', + parser.add_argument('modules', + nargs='+', help='The soong build module to run ' '(e.g. framework-minus-apex or services.core.unboosted)') @@ -170,4 +199,4 @@ def _setup_parser(): return parser if __name__ == "__main__": - SoongLintFix().run()
\ No newline at end of file + SoongLintFix().run() diff --git a/tools/lint/framework/Android.bp b/tools/lint/framework/Android.bp index 30a6daaef2a4..5acdf436ae08 100644 --- a/tools/lint/framework/Android.bp +++ b/tools/lint/framework/Android.bp @@ -37,28 +37,9 @@ java_library_host { java_test_host { name: "AndroidFrameworkLintCheckerTest", + defaults: ["AndroidLintCheckerTestDefaults"], srcs: ["checks/src/test/java/**/*.kt"], static_libs: [ "AndroidFrameworkLintChecker", - "junit", - "lint", - "lint_tests", ], - test_options: { - unit_test: true, - tradefed_options: [ - { - // lint bundles in some classes that were built with older versions - // of libraries, and no longer load. Since tradefed tries to load - // all classes in the jar to look for tests, it crashes loading them. - // Exclude these classes from tradefed's search. - name: "exclude-paths", - value: "org/apache", - }, - { - name: "exclude-paths", - value: "META-INF", - }, - ], - }, } diff --git a/tools/lint/global/Android.bp b/tools/lint/global/Android.bp index bedb7bd78a29..3e74171814ab 100644 --- a/tools/lint/global/Android.bp +++ b/tools/lint/global/Android.bp @@ -38,28 +38,9 @@ java_library_host { java_test_host { name: "AndroidGlobalLintCheckerTest", + defaults: ["AndroidLintCheckerTestDefaults"], srcs: ["checks/src/test/java/**/*.kt"], static_libs: [ "AndroidGlobalLintChecker", - "junit", - "lint", - "lint_tests", ], - test_options: { - unit_test: true, - tradefed_options: [ - { - // lint bundles in some classes that were built with older versions - // of libraries, and no longer load. Since tradefed tries to load - // all classes in the jar to look for tests, it crashes loading them. - // Exclude these classes from tradefed's search. - name: "exclude-paths", - value: "org/apache", - }, - { - name: "exclude-paths", - value: "META-INF", - }, - ], - }, } diff --git a/tools/lint/utils/Android.bp b/tools/lint/utils/Android.bp new file mode 100644 index 000000000000..75e8d6863c20 --- /dev/null +++ b/tools/lint/utils/Android.bp @@ -0,0 +1,45 @@ +// Copyright (C) 2023 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 { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "frameworks_base_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["frameworks_base_license"], +} + +java_library_host { + name: "AndroidUtilsLintChecker", + srcs: ["checks/src/main/java/**/*.kt"], + plugins: ["auto_service_plugin"], + libs: [ + "auto_service_annotations", + "lint_api", + ], + static_libs: [ + "AndroidCommonLint", + ], + kotlincflags: ["-Xjvm-default=all"], +} + +java_test_host { + name: "AndroidUtilsLintCheckerTest", + defaults: ["AndroidLintCheckerTestDefaults"], + srcs: ["checks/src/test/java/**/*.kt"], + static_libs: [ + "AndroidUtilsLintChecker", + ], +} diff --git a/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt b/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt new file mode 100644 index 000000000000..fa61c42ef8e6 --- /dev/null +++ b/tools/lint/utils/checks/src/main/java/com/google/android/lint/AndroidUtilsIssueRegistry.kt @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2023 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.google.android.lint + +import com.android.tools.lint.client.api.IssueRegistry +import com.android.tools.lint.client.api.Vendor +import com.android.tools.lint.detector.api.CURRENT_API +import com.google.android.lint.aidl.AnnotatedAidlCounter +import com.google.auto.service.AutoService + +@AutoService(IssueRegistry::class) +@Suppress("UnstableApiUsage") +class AndroidUtilsIssueRegistry : IssueRegistry() { + override val issues = listOf( + AnnotatedAidlCounter.ISSUE_ANNOTATED_AIDL_COUNTER, + ) + + override val api: Int + get() = CURRENT_API + + override val minApi: Int + get() = 8 + + override val vendor: Vendor = Vendor( + vendorName = "Android", + feedbackUrl = "http://b/issues/new?component=315013", + contact = "tweek@google.com" + ) +} diff --git a/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/AnnotatedAidlCounter.kt b/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/AnnotatedAidlCounter.kt new file mode 100644 index 000000000000..f0ec3f44f6c4 --- /dev/null +++ b/tools/lint/utils/checks/src/main/java/com/google/android/lint/aidl/AnnotatedAidlCounter.kt @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2023 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.google.android.lint.aidl + +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Context +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Location +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import org.jetbrains.uast.UBlockExpression +import org.jetbrains.uast.UMethod + +import java.util.TreeMap + +/** + * Count the number of AIDL interfaces. Reports the number of annotated and + * non-annotated methods. + */ +@Suppress("UnstableApiUsage") +class AnnotatedAidlCounter : AidlImplementationDetector() { + + private data class Stat( + var unannotated: Int = 0, + var enforced: Int = 0, + var notRequired: Int = 0, + ) + + private var packagesStats: TreeMap<String, Stat> = TreeMap<String, Stat>() + + override fun visitAidlMethod( + context: JavaContext, + node: UMethod, + interfaceName: String, + body: UBlockExpression + ) { + val packageName = context.uastFile?.packageName ?: "<unknown>" + var packageStat = packagesStats.getOrDefault(packageName, Stat()) + when { + node.hasAnnotation(ANNOTATION_ENFORCE_PERMISSION) -> packageStat.enforced += 1 + node.hasAnnotation(ANNOTATION_REQUIRES_NO_PERMISSION) -> packageStat.notRequired += 1 + else -> packageStat.unannotated += 1 + } + packagesStats.put(packageName, packageStat) + // context.driver.client.log(null, "%s.%s#%s".format(packageName, interfaceName, node.name)) + } + + override fun afterCheckRootProject(context: Context) { + var total = Stat() + for ((packageName, stat) in packagesStats) { + context.client.log(null, "package $packageName => $stat") + total.unannotated += stat.unannotated + total.enforced += stat.enforced + total.notRequired += stat.notRequired + } + val location = Location.create(context.project.dir) + context.report( + ISSUE_ANNOTATED_AIDL_COUNTER, + location, + "module ${context.project.name} => $total" + ) + } + + companion object { + + @JvmField + val ISSUE_ANNOTATED_AIDL_COUNTER = Issue.create( + id = "AnnotatedAidlCounter", + briefDescription = "Statistics on the number of annotated AIDL methods.", + explanation = "", + category = Category.SECURITY, + priority = 5, + severity = Severity.INFORMATIONAL, + implementation = Implementation( + AnnotatedAidlCounter::class.java, + Scope.JAVA_FILE_SCOPE + ), + ) + } +} diff --git a/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/AnnotatedAidlCounterTest.kt b/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/AnnotatedAidlCounterTest.kt new file mode 100644 index 000000000000..692b7da243c9 --- /dev/null +++ b/tools/lint/utils/checks/src/test/java/com/google/android/lint/aidl/AnnotatedAidlCounterTest.kt @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2023 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.google.android.lint.aidl + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.checks.infrastructure.TestLintTask +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue + +@Suppress("UnstableApiUsage") +class AnnotatedAidlCounterTest : LintDetectorTest() { + override fun getDetector(): Detector = AnnotatedAidlCounter() + + override fun getIssues(): List<Issue> = listOf( + AnnotatedAidlCounter.ISSUE_ANNOTATED_AIDL_COUNTER, + ) + + override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) + + /** No issue scenario */ + + fun testDoesNotDetectIssuesCorrectAnnotationOnMethod() { + lint().files(java( + """ + package test.pkg; + import android.annotation.EnforcePermission; + public class TestClass2 extends IFooMethod.Stub { + @Override + @EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) + public void testMethod() {} + } + """).indented(), + *stubs + ) + .run() + .expect(""" + app: Information: module app => Stat(unannotated=0, enforced=1, notRequired=0) [AnnotatedAidlCounter] + 0 errors, 0 warnings + """) + } + + // A service with permission annotation on the method. + private val interfaceIFooMethodStub: TestFile = java( + """ + public interface IFooMethod extends android.os.IInterface { + public static abstract class Stub extends android.os.Binder implements IFooMethod {} + @android.annotation.EnforcePermission(android.Manifest.permission.READ_PHONE_STATE) + public void testMethod(); + } + """ + ).indented() + + // A service without any permission annotation. + private val interfaceIBarStub: TestFile = java( + """ + public interface IBar extends android.os.IInterface { + public static abstract class Stub extends android.os.Binder implements IBar { + @Override + public void testMethod() {} + } + public void testMethod(); + } + """ + ).indented() + + private val manifestPermissionStub: TestFile = java( + """ + package android.Manifest; + class permission { + public static final String READ_PHONE_STATE = "android.permission.READ_PHONE_STATE"; + } + """ + ).indented() + + private val enforcePermissionAnnotationStub: TestFile = java( + """ + package android.annotation; + public @interface EnforcePermission {} + """ + ).indented() + + private val stubs = arrayOf(interfaceIFooMethodStub, interfaceIBarStub, + manifestPermissionStub, enforcePermissionAnnotationStub) +} |