summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ApiDocs.bp16
-rw-r--r--OWNERS1
-rw-r--r--TRACE_OWNERS5
-rw-r--r--apex/jobscheduler/framework/java/android/app/AlarmManager.java10
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java74
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java160
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java3
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java3
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java6
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java6
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java6
-rw-r--r--cmds/bootanimation/BootAnimation.cpp16
-rw-r--r--cmds/bootanimation/BootAnimation.h1
-rw-r--r--core/api/current.txt6
-rw-r--r--core/api/test-current.txt4
-rw-r--r--core/java/android/accessibilityservice/MagnificationConfig.java13
-rw-r--r--core/java/android/app/UiAutomation.java4
-rw-r--r--core/java/android/app/WindowConfiguration.java3
-rw-r--r--core/java/android/app/ambientcontext/IAmbientContextManager.aidl4
-rw-r--r--core/java/android/companion/virtual/IVirtualDevice.aidl6
-rw-r--r--core/java/android/companion/virtual/audio/IAudioConfigChangedCallback.aidl (renamed from core/java/android/companion/virtual/audio/IAudioSessionCallback.aidl)10
-rw-r--r--core/java/android/companion/virtual/audio/IAudioRoutingCallback.aidl28
-rw-r--r--core/java/android/companion/virtual/audio/VirtualAudioDevice.java10
-rw-r--r--core/java/android/companion/virtual/audio/VirtualAudioSession.java62
-rw-r--r--core/java/android/content/ClipDescription.java20
-rw-r--r--core/java/android/content/pm/PackageManager.java2
-rw-r--r--core/java/android/os/OWNERS3
-rw-r--r--core/java/android/os/Trace.java47
-rw-r--r--core/java/android/view/ViewRootImpl.java7
-rw-r--r--core/java/android/view/WindowInsets.java7
-rw-r--r--core/java/android/view/translation/UiTranslationManager.java40
-rw-r--r--core/java/android/window/OnBackInvokedDispatcher.java20
-rw-r--r--core/java/android/window/PictureInPictureSurfaceTransaction.java30
-rw-r--r--core/java/android/window/WindowOnBackInvokedDispatcher.java18
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java12
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java96
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java5
-rw-r--r--core/java/com/android/internal/policy/DecorView.java5
-rw-r--r--core/jni/OWNERS1
-rw-r--r--core/jni/android_hardware_input_InputApplicationHandle.cpp5
-rw-r--r--core/jni/android_hardware_input_InputWindowHandle.cpp7
-rw-r--r--core/jni/android_os_Trace.cpp26
-rw-r--r--core/res/res/values/config.xml11
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/companion/virtual/audio/VirtualAudioSessionTest.java4
-rw-r--r--identity/java/android/security/identity/CredstoreIdentityCredentialStore.java13
-rw-r--r--keystore/java/android/security/KeyStoreException.java153
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java58
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java9
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java13
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java21
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenShellTransit.kt44
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenShellTransit.kt42
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt19
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenShellTransit.kt42
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest_ShellTransit.kt64
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt3
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestShellTransit.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTestShellTransit.kt49
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java6
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp10
-rw-r--r--media/jni/soundpool/SoundPool.cpp5
-rw-r--r--media/jni/soundpool/SoundPool.h2
-rw-r--r--media/jni/soundpool/StreamManager.cpp4
-rw-r--r--media/jni/soundpool/StreamManager.h2
-rw-r--r--media/jni/soundpool/android_media_SoundPool.cpp2
-rw-r--r--media/jni/soundpool/tests/soundpool_stress.cpp2
-rw-r--r--packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java69
-rw-r--r--packages/SettingsLib/res/values/strings.xml2
-rw-r--r--packages/Shell/AndroidManifest.xml6
-rw-r--r--packages/SystemUI/res/values/strings.xml3
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java29
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/LockIconViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerFactory.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt45
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java115
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java88
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java38
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEventTest.java93
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java94
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java283
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java12
-rw-r--r--services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java11
-rw-r--r--services/companion/java/com/android/server/companion/virtual/audio/AudioPlaybackDetector.java6
-rw-r--r--services/companion/java/com/android/server/companion/virtual/audio/AudioRecordingDetector.java6
-rw-r--r--services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java35
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java98
-rw-r--r--services/core/java/com/android/server/AlarmManagerInternal.java5
-rw-r--r--services/core/java/com/android/server/am/AppBatteryTracker.java118
-rw-r--r--services/core/java/com/android/server/am/AppRestrictionController.java30
-rw-r--r--services/core/java/com/android/server/am/BaseAppStatePolicy.java6
-rw-r--r--services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java13
-rw-r--r--services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java16
-rw-r--r--services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java5
-rw-r--r--services/core/java/com/android/server/biometrics/BiometricSensor.java18
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java57
-rw-r--r--services/core/java/com/android/server/display/OWNERS1
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java28
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java4
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerService.java3
-rw-r--r--services/core/java/com/android/server/pm/Computer.java26
-rw-r--r--services/core/java/com/android/server/pm/ComputerEngine.java108
-rw-r--r--services/core/java/com/android/server/pm/DeletePackageHelper.java1
-rw-r--r--services/core/java/com/android/server/pm/DumpHelper.java316
-rw-r--r--services/core/java/com/android/server/pm/IPackageManagerBase.java2
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java2
-rw-r--r--services/core/java/com/android/server/pm/Installer.java14
-rw-r--r--services/core/java/com/android/server/pm/IntentResolverInterceptor.java2
-rw-r--r--services/core/java/com/android/server/pm/KnownPackages.java213
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java159
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java131
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java1
-rw-r--r--services/core/java/com/android/server/pm/RemovePackageHelper.java17
-rw-r--r--services/core/java/com/android/server/pm/StorageEventHelper.java35
-rw-r--r--services/core/java/com/android/server/pm/SuspendPackageHelper.java18
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java11
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java25
-rw-r--r--services/core/java/com/android/server/pm/resolution/ComponentResolver.java116
-rw-r--r--services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java19
-rw-r--r--services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java119
-rw-r--r--services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java49
-rw-r--r--services/core/java/com/android/server/utils/WatchedArraySet.java12
-rw-r--r--services/core/java/com/android/server/wm/ActivityClientController.java3
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java38
-rw-r--r--services/core/java/com/android/server/wm/DisplayFrames.java13
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java4
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java2
-rw-r--r--services/core/java/com/android/server/wm/Task.java5
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java65
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java255
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java121
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java8
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt10
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java44
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java29
-rw-r--r--services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java2
-rw-r--r--services/translation/java/com/android/server/translation/TranslationManagerService.java12
-rw-r--r--services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java194
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java18
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java5
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt33
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt41
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt10
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest_ShellTransit.kt60
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest_ShellTransit.kt6
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt3
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest_ShellTransit.kt62
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt55
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt9
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestShellTransit.kt147
195 files changed, 3455 insertions, 2348 deletions
diff --git a/ApiDocs.bp b/ApiDocs.bp
index 038ee6501ded..5ec107da8b94 100644
--- a/ApiDocs.bp
+++ b/ApiDocs.bp
@@ -231,7 +231,7 @@ droiddoc {
"android.whichdoc offline",
],
compat_config: ":global-compat-config",
- proofread_file: "offline-sdk-docs-proofrerad.txt",
+ proofread_file: "offline-sdk-docs-proofread.txt",
args: framework_docs_only_args + " -offlinemode -title \"Android SDK\"",
static_doc_index_redirect: "docs/docs-preview-index.html",
}
@@ -248,7 +248,7 @@ droiddoc {
hdf: [
"android.whichdoc offline",
],
- proofread_file: "offline-sdk-referenceonly-docs-proofrerad.txt",
+ proofread_file: "offline-sdk-referenceonly-docs-proofread.txt",
args: framework_docs_only_args + " -offlinemode -title \"Android SDK\" -referenceonly",
static_doc_index_redirect: "docs/docs-documentation-redirect.html",
static_doc_properties: "docs/source.properties",
@@ -266,7 +266,7 @@ droiddoc {
hdf: [
"android.whichdoc offline",
],
- proofread_file: "offline-system-sdk-referenceonly-docs-proofrerad.txt",
+ proofread_file: "offline-system-sdk-referenceonly-docs-proofread.txt",
args: framework_docs_only_args + " -hide 101 -hide 104 -hide 108" +
" -offlinemode -title \"Android System SDK\" -referenceonly",
static_doc_index_redirect: "docs/docs-documentation-redirect.html",
@@ -283,7 +283,7 @@ droiddoc {
"android.whichdoc online",
"android.hasSamples true",
],
- proofread_file: "online-sdk-docs-proofrerad.txt",
+ proofread_file: "online-sdk-docs-proofread.txt",
args: framework_docs_only_args +
" -toroot / -samplegroup Admin " +
" -samplegroup Background " +
@@ -312,7 +312,7 @@ droiddoc {
"android.whichdoc online",
"android.hasSamples true",
],
- proofread_file: "online-system-api-sdk-docs-proofrerad.txt",
+ proofread_file: "online-system-api-sdk-docs-proofread.txt",
args: framework_docs_only_args +
" -referenceonly " +
" -title \"Android SDK - Including system APIs.\" " +
@@ -347,7 +347,7 @@ droiddoc {
"android.whichdoc online",
"android.hasSamples true",
],
- proofread_file: "ds-docs-proofrerad.txt",
+ proofread_file: "ds-docs-proofread.txt",
args: framework_docs_only_args +
" -toroot / -yamlV2 -metalavaApiSince -samplegroup Admin " +
" -samplegroup Background " +
@@ -458,7 +458,7 @@ droiddoc {
"android.whichdoc online",
"android.hasSamples true",
],
- proofread_file: "online-sdk-dev-docs-proofrerad.txt",
+ proofread_file: "online-sdk-dev-docs-proofread.txt",
args: framework_docs_only_args +
" -toroot / -samplegroup Admin " +
" -samplegroup Background " +
@@ -483,7 +483,7 @@ droiddoc {
srcs: [
":framework-doc-stubs",
],
- proofread_file: "hidden-docs-proofrerad.txt",
+ proofread_file: "hidden-docs-proofread.txt",
args: framework_docs_only_args +
" -referenceonly " +
" -title \"Android SDK - Including hidden APIs.\"",
diff --git a/OWNERS b/OWNERS
index 47d8c83fea03..d4d19365f4d1 100644
--- a/OWNERS
+++ b/OWNERS
@@ -31,5 +31,6 @@ per-file */res*/values*/*.xml = byi@google.com, delphij@google.com
per-file *.bp = file:platform/build/soong:/OWNERS #{LAST_RESORT_SUGGESTION}
per-file Android.mk = file:platform/build/soong:/OWNERS #{LAST_RESORT_SUGGESTION}
+per-file framework-jarjar-rules.txt = file:platform/build/soong:/OWNERS #{LAST_RESORT_SUGGESTION}
per-file TestProtoLibraries.bp = file:platform/platform_testing:/libraries/health/OWNERS
per-file TestProtoLibraries.bp = file:platform/tools/tradefederation:/OWNERS
diff --git a/TRACE_OWNERS b/TRACE_OWNERS
new file mode 100644
index 000000000000..f746a162bc8f
--- /dev/null
+++ b/TRACE_OWNERS
@@ -0,0 +1,5 @@
+# OWNERS of Trace-related files
+primiano@google.com
+timmurray@google.com
+jjaggi@google.com
+jreck@google.com
diff --git a/apex/jobscheduler/framework/java/android/app/AlarmManager.java b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
index da429af7e351..61424ae0e158 100644
--- a/apex/jobscheduler/framework/java/android/app/AlarmManager.java
+++ b/apex/jobscheduler/framework/java/android/app/AlarmManager.java
@@ -270,6 +270,16 @@ public class AlarmManager {
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.S)
public static final long ENFORCE_MINIMUM_WINDOW_ON_INEXACT_ALARMS = 185199076L;
+ /**
+ * For apps targeting {@link Build.VERSION_CODES#TIRAMISU} or above, certain kinds of apps can
+ * use {@link Manifest.permission#USE_EXACT_ALARM} to schedule exact alarms.
+ *
+ * @hide
+ */
+ @ChangeId
+ @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
+ public static final long ENABLE_USE_EXACT_ALARM = 218533173L;
+
@UnsupportedAppUsage
private final IAlarmManager mService;
private final Context mContext;
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index a09f39f26eab..f67e8d2baa11 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -1827,30 +1827,9 @@ public class AlarmManagerService extends SystemService {
newAppIds.add(UserHandle.getAppId(uid));
}
}
- final ArraySet<Integer> removed = new ArraySet<>(mExactAlarmCandidates);
- removed.removeAll(newAppIds);
- // This code is only called on package_added and boot. The set {removed} is only expected to
- // be non-empty when a package was updated and it removed the permission from its manifest.
- for (int i = 0; i < removed.size(); i++) {
- final int removedAppId = removed.valueAt(i);
- synchronized (mLock) {
- Slog.i(TAG, "App id " + removedAppId + " lost SCHEDULE_EXACT_ALARM on update");
+ // Some packages may have lost permission to schedule exact alarms on update, their alarms
+ // will be removed while handling CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE after this.
- final Predicate<Alarm> whichAlarms = a -> {
- if (UserHandle.getAppId(a.uid) != removedAppId || a.windowLength != 0) {
- return false;
- }
- if (!isExactAlarmChangeEnabled(a.packageName, UserHandle.getUserId(a.uid))) {
- return false;
- }
- if (hasUseExactAlarmPermission(a.packageName, a.uid)) {
- return false;
- }
- return !isExemptFromExactAlarmPermission(a.uid);
- };
- removeAlarmsInternalLocked(whichAlarms, REMOVE_REASON_EXACT_PERMISSION_REVOKED);
- }
- }
// No need to lock. Assignment is always atomic.
mExactAlarmCandidates = Collections.unmodifiableSet(newAppIds);
}
@@ -1910,7 +1889,7 @@ public class AlarmManagerService extends SystemService {
|| !isExactAlarmChangeEnabled(packageName, userId)) {
return;
}
- if (hasUseExactAlarmPermission(packageName, uid)) {
+ if (hasUseExactAlarmInternal(packageName, uid)) {
return;
}
@@ -2533,8 +2512,9 @@ public class AlarmManagerService extends SystemService {
}
@Override
- public boolean hasScheduleExactAlarm(String packageName, int uid) {
- return hasScheduleExactAlarmInternal(packageName, uid);
+ public boolean hasExactAlarmPermission(String packageName, int uid) {
+ return hasScheduleExactAlarmInternal(packageName, uid)
+ || hasUseExactAlarmInternal(packageName, uid);
}
@Override
@@ -2558,21 +2538,19 @@ public class AlarmManagerService extends SystemService {
return appOpMode == AppOpsManager.MODE_ALLOWED;
}
- boolean hasUseExactAlarmPermission(String packageName, int uid) {
- return PermissionChecker.checkPermissionForPreflight(getContext(),
+ boolean hasUseExactAlarmInternal(String packageName, int uid) {
+ return isUseExactAlarmEnabled(packageName, UserHandle.getUserId(uid))
+ && (PermissionChecker.checkPermissionForPreflight(getContext(),
Manifest.permission.USE_EXACT_ALARM, PermissionChecker.PID_UNKNOWN, uid,
- packageName) == PermissionChecker.PERMISSION_GRANTED;
+ packageName) == PermissionChecker.PERMISSION_GRANTED);
}
boolean hasScheduleExactAlarmInternal(String packageName, int uid) {
- if (hasUseExactAlarmPermission(packageName, uid)) {
- return true;
- }
+ final long start = mStatLogger.getTime();
+
// Not using getScheduleExactAlarmState as this can avoid some calls to AppOpsService.
// Not using #mLastOpScheduleExactAlarm as it may contain stale values.
// No locking needed as all internal containers being queried are immutable.
-
- final long start = mStatLogger.getTime();
final boolean hasPermission;
if (!mExactAlarmCandidates.contains(UserHandle.getAppId(uid))) {
hasPermission = false;
@@ -2703,7 +2681,8 @@ public class AlarmManagerService extends SystemService {
lowerQuota = allowWhileIdle;
idleOptions = allowWhileIdle ? mOptsWithFgs.toBundle() : null;
}
- if (needsPermission && !hasScheduleExactAlarmInternal(callingPackage, callingUid)) {
+ if (needsPermission && !hasScheduleExactAlarmInternal(callingPackage, callingUid)
+ && !hasUseExactAlarmInternal(callingPackage, callingUid)) {
if (!isExemptFromExactAlarmPermission(callingUid)) {
final String errorMessage = "Caller " + callingPackage + " needs to hold "
+ Manifest.permission.SCHEDULE_EXACT_ALARM + " to set "
@@ -2768,7 +2747,8 @@ public class AlarmManagerService extends SystemService {
return true;
}
return isExemptFromExactAlarmPermission(packageUid)
- || hasScheduleExactAlarmInternal(packageName, packageUid);
+ || hasScheduleExactAlarmInternal(packageName, packageUid)
+ || hasUseExactAlarmInternal(packageName, packageUid);
}
@Override
@@ -2875,6 +2855,11 @@ public class AlarmManagerService extends SystemService {
packageName, UserHandle.of(userId));
}
+ private static boolean isUseExactAlarmEnabled(String packageName, int userId) {
+ return CompatChanges.isChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM,
+ packageName, UserHandle.of(userId));
+ }
+
@NeverCompile // Avoid size overhead of debugging code.
void dumpImpl(IndentingPrintWriter pw) {
synchronized (mLock) {
@@ -3784,7 +3769,7 @@ public class AlarmManagerService extends SystemService {
if (!isExactAlarmChangeEnabled(changedPackage, userId)) {
continue;
}
- if (hasUseExactAlarmPermission(changedPackage, uid)) {
+ if (hasUseExactAlarmInternal(changedPackage, uid)) {
continue;
}
final int appOpMode;
@@ -3817,8 +3802,9 @@ public class AlarmManagerService extends SystemService {
}
/**
- * Called when an app loses {@link Manifest.permission#SCHEDULE_EXACT_ALARM} to remove alarms
- * that the app is no longer eligible to use.
+ * Called when an app loses the permission to use exact alarms. This will happen when the app
+ * no longer has either {@link Manifest.permission#SCHEDULE_EXACT_ALARM} or
+ * {@link Manifest.permission#USE_EXACT_ALARM}.
*
* This is not expected to get called frequently.
*/
@@ -3828,7 +3814,8 @@ public class AlarmManagerService extends SystemService {
|| !isExactAlarmChangeEnabled(packageName, UserHandle.getUserId(uid))) {
return;
}
- Slog.w(TAG, "Package " + packageName + ", uid " + uid + " lost SCHEDULE_EXACT_ALARM!");
+ Slog.w(TAG, "Package " + packageName + ", uid " + uid
+ + " lost permission to set exact alarms!");
final Predicate<Alarm> whichAlarms = a -> (a.uid == uid && a.packageName.equals(packageName)
&& a.windowLength == 0);
@@ -4764,7 +4751,8 @@ public class AlarmManagerService extends SystemService {
case CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE:
packageName = (String) msg.obj;
uid = msg.arg1;
- if (!hasScheduleExactAlarmInternal(packageName, uid)) {
+ if (!hasScheduleExactAlarmInternal(packageName, uid)
+ && !hasUseExactAlarmInternal(packageName, uid)) {
synchronized (mLock) {
removeExactAlarmsOnPermissionRevokedLocked(uid,
packageName, /*killUid = */false);
@@ -4936,13 +4924,15 @@ public class AlarmManagerService extends SystemService {
mLastOpScheduleExactAlarm.delete(uid);
return;
case Intent.ACTION_PACKAGE_ADDED:
+ mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES);
if (intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+ // Some apps may lose permission to set exact alarms on update.
+ // We need to remove their exact alarms.
final String packageUpdated = intent.getData().getSchemeSpecificPart();
mHandler.obtainMessage(
AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE, uid, -1,
packageUpdated).sendToTarget();
}
- mHandler.sendEmptyMessage(AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES);
return;
case Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE:
pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
index 549badd5ba82..b4238c975d98 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -16,7 +16,6 @@
package com.android.server.job;
-import static com.android.server.job.JobSchedulerService.MAX_JOB_CONTEXTS_COUNT;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
@@ -82,6 +81,11 @@ class JobConcurrencyManager {
private static final String TAG = JobSchedulerService.TAG + ".Concurrency";
private static final boolean DEBUG = JobSchedulerService.DEBUG;
+ /** The maximum number of concurrent jobs we'll aim to run at one time. */
+ public static final int STANDARD_CONCURRENCY_LIMIT = 16;
+ /** The maximum number of objects we should retain in memory when not in use. */
+ private static final int MAX_RETAINED_OBJECTS = (int) (1.5 * STANDARD_CONCURRENCY_LIMIT);
+
static final String CONFIG_KEY_PREFIX_CONCURRENCY = "concurrency_";
private static final String KEY_SCREEN_OFF_ADJUSTMENT_DELAY_MS =
CONFIG_KEY_PREFIX_CONCURRENCY + "screen_off_adjustment_delay_ms";
@@ -93,7 +97,7 @@ class JobConcurrencyManager {
@VisibleForTesting
static final String KEY_PKG_CONCURRENCY_LIMIT_REGULAR =
CONFIG_KEY_PREFIX_CONCURRENCY + "pkg_concurrency_limit_regular";
- private static final int DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR = MAX_JOB_CONTEXTS_COUNT / 2;
+ private static final int DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR = STANDARD_CONCURRENCY_LIMIT / 2;
/**
* Set of possible execution types that a job can have. The actual type(s) of a job are based
@@ -309,7 +313,7 @@ class JobConcurrencyManager {
private final ArrayList<ContextAssignment> mRecycledStoppable = new ArrayList<>();
private final Pools.Pool<ContextAssignment> mContextAssignmentPool =
- new Pools.SimplePool<>(MAX_JOB_CONTEXTS_COUNT);
+ new Pools.SimplePool<>(MAX_RETAINED_OBJECTS);
/**
* Set of JobServiceContexts that are actively running jobs.
@@ -317,14 +321,16 @@ class JobConcurrencyManager {
final List<JobServiceContext> mActiveServices = new ArrayList<>();
/** Set of JobServiceContexts that aren't currently running any jobs. */
- final ArraySet<JobServiceContext> mIdleContexts = new ArraySet<>();
+ private final ArraySet<JobServiceContext> mIdleContexts = new ArraySet<>();
+
+ private int mNumDroppedContexts = 0;
private final ArraySet<JobStatus> mRunningJobs = new ArraySet<>();
private final WorkCountTracker mWorkCountTracker = new WorkCountTracker();
private final Pools.Pool<PackageStats> mPkgStatsPool =
- new Pools.SimplePool<>(MAX_JOB_CONTEXTS_COUNT);
+ new Pools.SimplePool<>(MAX_RETAINED_OBJECTS);
private final SparseArrayMap<String, PackageStats> mActivePkgStats = new SparseArrayMap<>();
@@ -406,7 +412,7 @@ class JobConcurrencyManager {
void onThirdPartyAppsCanStart() {
final IBatteryStats batteryStats = IBatteryStats.Stub.asInterface(
ServiceManager.getService(BatteryStats.SERVICE_NAME));
- for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
+ for (int i = 0; i < STANDARD_CONCURRENCY_LIMIT; i++) {
mIdleContexts.add(
new JobServiceContext(mService, this, batteryStats,
mService.mJobPackageTracker, mContext.getMainLooper()));
@@ -655,13 +661,13 @@ class JobConcurrencyManager {
}
preferredUidOnly.sort(sDeterminationComparator);
stoppable.sort(sDeterminationComparator);
- for (int i = numRunningJobs; i < MAX_JOB_CONTEXTS_COUNT; ++i) {
+ for (int i = numRunningJobs; i < STANDARD_CONCURRENCY_LIMIT; ++i) {
final JobServiceContext jsc;
final int numIdleContexts = mIdleContexts.size();
if (numIdleContexts > 0) {
jsc = mIdleContexts.removeAt(numIdleContexts - 1);
} else {
- Slog.wtf(TAG, "Had fewer than " + MAX_JOB_CONTEXTS_COUNT + " in existence");
+ Slog.wtf(TAG, "Had fewer than " + STANDARD_CONCURRENCY_LIMIT + " in existence");
jsc = createNewJobServiceContext();
}
@@ -681,6 +687,7 @@ class JobConcurrencyManager {
JobStatus nextPending;
pendingJobQueue.resetIterator();
+ int projectedRunningCount = numRunningJobs;
while ((nextPending = pendingJobQueue.next()) != null) {
if (mRunningJobs.contains(nextPending)) {
continue;
@@ -694,6 +701,9 @@ class JobConcurrencyManager {
ContextAssignment selectedContext = null;
final int allWorkTypes = getJobWorkTypes(nextPending);
final boolean pkgConcurrencyOkay = !isPkgConcurrencyLimitedLocked(nextPending);
+ final boolean isTopEj = nextPending.shouldTreatAsExpeditedJob()
+ && nextPending.lastEvaluatedBias == JobInfo.BIAS_TOP_APP;
+ final boolean isInOverage = projectedRunningCount > STANDARD_CONCURRENCY_LIMIT;
boolean startingJob = false;
if (idle.size() > 0) {
final int idx = idle.size() - 1;
@@ -711,14 +721,36 @@ class JobConcurrencyManager {
assignment.newWorkType = workType;
}
}
- if (selectedContext == null) {
+ if (selectedContext == null && stoppable.size() > 0) {
+ int topEjCount = 0;
+ for (int r = mRunningJobs.size() - 1; r >= 0; --r) {
+ JobStatus js = mRunningJobs.valueAt(r);
+ if (js.startedAsExpeditedJob && js.lastEvaluatedBias == JobInfo.BIAS_TOP_APP) {
+ topEjCount++;
+ }
+ }
for (int s = stoppable.size() - 1; s >= 0; --s) {
final ContextAssignment assignment = stoppable.get(s);
final JobStatus runningJob = assignment.context.getRunningJobLocked();
- // Maybe stop the job if it has had its day in the sun. Don't let a different
- // app preempt jobs started for TOP apps though.
- if (runningJob.lastEvaluatedBias < JobInfo.BIAS_TOP_APP
- && assignment.shouldStopJobReason != null) {
+ // Maybe stop the job if it has had its day in the sun. Only allow replacing
+ // for one of the following conditions:
+ // 1. We're putting in the current TOP app's EJ
+ // 2. There aren't too many jobs running AND the current job started when the
+ // app was in the background
+ // 3. There aren't too many jobs running AND the current job started when the
+ // app was on TOP, but the app has since left TOP
+ // 4. There aren't too many jobs running AND the current job started when the
+ // app was on TOP, the app is still TOP, but there are too many TOP+EJs
+ // running (because we don't want them to starve out other apps and the
+ // current job has already run for the minimum guaranteed time).
+ boolean canReplace = isTopEj; // Case 1
+ if (!canReplace && !isInOverage) {
+ final int currentJobBias = mService.evaluateJobBiasLocked(runningJob);
+ canReplace = runningJob.lastEvaluatedBias < JobInfo.BIAS_TOP_APP // Case 2
+ || currentJobBias < JobInfo.BIAS_TOP_APP // Case 3
+ || topEjCount > .5 * mWorkTypeConfig.getMaxTotal(); // Case 4
+ }
+ if (canReplace) {
int replaceWorkType = mWorkCountTracker.canJobStart(allWorkTypes,
assignment.context.getRunningJobWorkType());
if (replaceWorkType != WORK_TYPE_NONE) {
@@ -736,7 +768,7 @@ class JobConcurrencyManager {
}
}
}
- if (selectedContext == null) {
+ if (selectedContext == null && (!isInOverage || isTopEj)) {
int lowestBiasSeen = Integer.MAX_VALUE;
for (int p = preferredUidOnly.size() - 1; p >= 0; --p) {
final ContextAssignment assignment = preferredUidOnly.get(p);
@@ -765,10 +797,43 @@ class JobConcurrencyManager {
preferredUidOnly.remove(selectedContext);
}
}
+ // Make sure to run EJs for the TOP app immediately.
+ if (isTopEj) {
+ if (selectedContext != null
+ && selectedContext.context.getRunningJobLocked() != null) {
+ // We're "replacing" a currently running job, but we want TOP EJs to start
+ // immediately, so we'll start the EJ on a fresh available context and
+ // stop this currently running job to replace in two steps.
+ changed.add(selectedContext);
+ projectedRunningCount--;
+ selectedContext.newJob = null;
+ selectedContext.newWorkType = WORK_TYPE_NONE;
+ selectedContext = null;
+ }
+ if (selectedContext == null) {
+ selectedContext = mContextAssignmentPool.acquire();
+ if (selectedContext == null) {
+ selectedContext = new ContextAssignment();
+ }
+ selectedContext.context = mIdleContexts.size() > 0
+ ? mIdleContexts.removeAt(mIdleContexts.size() - 1)
+ : createNewJobServiceContext();
+ selectedContext.newJob = nextPending;
+ final int workType = mWorkCountTracker.canJobStart(allWorkTypes);
+ selectedContext.newWorkType =
+ (workType != WORK_TYPE_NONE) ? workType : WORK_TYPE_TOP;
+ }
+ }
final PackageStats packageStats = getPkgStatsLocked(
nextPending.getSourceUserId(), nextPending.getSourcePackageName());
if (selectedContext != null) {
changed.add(selectedContext);
+ if (selectedContext.context.getRunningJobLocked() != null) {
+ projectedRunningCount--;
+ }
+ if (selectedContext.newJob != null) {
+ projectedRunningCount++;
+ }
packageStats.adjustStagedCount(true, nextPending.shouldTreatAsExpeditedJob());
}
if (startingJob) {
@@ -793,7 +858,7 @@ class JobConcurrencyManager {
if (DEBUG) {
Slog.d(TAG, "preempting job: " + js);
}
- // preferredUid will be set to uid of currently running job.
+ // preferredUid will be set to uid of currently running job, if appropriate.
assignment.context.cancelExecutingJobLocked(
assignment.preemptReasonCode,
JobParameters.INTERNAL_STOP_REASON_PREEMPT, assignment.preemptReason);
@@ -811,9 +876,6 @@ class JobConcurrencyManager {
}
for (int s = stoppable.size() - 1; s >= 0; --s) {
final ContextAssignment assignment = stoppable.get(s);
- // The preferred UID is set when we cancel with PREEMPT reason, but don't preserve the
- // UID for any stoppable contexts since we want to open the context up to any/all apps.
- assignment.context.clearPreferredUid();
assignment.clear();
mContextAssignmentPool.release(assignment);
}
@@ -838,6 +900,21 @@ class JobConcurrencyManager {
}
@GuardedBy("mLock")
+ void onUidBiasChangedLocked(int prevBias, int newBias) {
+ if (prevBias != JobInfo.BIAS_TOP_APP && newBias != JobInfo.BIAS_TOP_APP) {
+ // TOP app didn't change. Nothing to do.
+ return;
+ }
+ if (mService.getPendingJobQueue().size() == 0) {
+ // Nothing waiting for the top app to leave. Nothing to do.
+ return;
+ }
+ // Don't stop the TOP jobs directly. Instead, see if they would be replaced by some
+ // pending job (there may not always be something to replace them).
+ assignJobsToContextsLocked();
+ }
+
+ @GuardedBy("mLock")
boolean stopJobOnServiceContextLocked(JobStatus job,
@JobParameters.StopReason int reason, int internalReasonCode, String debugReason) {
if (!mRunningJobs.contains(job)) {
@@ -1041,7 +1118,13 @@ class JobConcurrencyManager {
mWorkCountTracker.onJobFinished(workType);
mRunningJobs.remove(jobStatus);
mActiveServices.remove(worker);
- mIdleContexts.add(worker);
+ if (mIdleContexts.size() < MAX_RETAINED_OBJECTS) {
+ // Don't need to save all new contexts, but keep some extra around in case we need
+ // extras for another TOP+EJ overage.
+ mIdleContexts.add(worker);
+ } else {
+ mNumDroppedContexts++;
+ }
final PackageStats packageStats =
mActivePkgStats.get(jobStatus.getSourceUserId(), jobStatus.getSourcePackageName());
if (packageStats == null) {
@@ -1054,6 +1137,14 @@ class JobConcurrencyManager {
}
}
+ if (mActiveServices.size() >= STANDARD_CONCURRENCY_LIMIT) {
+ worker.clearPreferredUid();
+ // We're over the limit (because the TOP app scheduled a lot of EJs). Don't start
+ // running anything new until we get back below the limit.
+ noteConcurrency();
+ return;
+ }
+
final PendingJobQueue pendingJobQueue = mService.getPendingJobQueue();
if (worker.getPreferredUid() != JobServiceContext.NO_PREFERRED_UID) {
updateCounterConfigLocked();
@@ -1245,6 +1336,18 @@ class JobConcurrencyManager {
}
} else if (mWorkCountTracker.getPendingJobCount(WORK_TYPE_EJ) > 0) {
return "blocking " + workTypeToString(WORK_TYPE_EJ) + " queue";
+ } else if (js.startedAsExpeditedJob && js.lastEvaluatedBias == JobInfo.BIAS_TOP_APP) {
+ // Try not to let TOP + EJ starve out other apps.
+ int topEjCount = 0;
+ for (int r = mRunningJobs.size() - 1; r >= 0; --r) {
+ JobStatus j = mRunningJobs.valueAt(r);
+ if (j.startedAsExpeditedJob && j.lastEvaluatedBias == JobInfo.BIAS_TOP_APP) {
+ topEjCount++;
+ }
+ }
+ if (topEjCount > .5 * mWorkTypeConfig.getMaxTotal()) {
+ return "prevent top EJ dominance";
+ }
}
// No other pending EJs. Return null so we don't let regular jobs preempt an EJ.
return null;
@@ -1361,10 +1464,10 @@ class JobConcurrencyManager {
CONFIG_LIMITS_SCREEN_OFF.low.update(properties);
CONFIG_LIMITS_SCREEN_OFF.critical.update(properties);
- // Package concurrency limits must in the range [1, MAX_JOB_CONTEXTS_COUNT].
- mPkgConcurrencyLimitEj = Math.max(1, Math.min(MAX_JOB_CONTEXTS_COUNT,
+ // Package concurrency limits must in the range [1, STANDARD_CONCURRENCY_LIMIT].
+ mPkgConcurrencyLimitEj = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT,
properties.getInt(KEY_PKG_CONCURRENCY_LIMIT_EJ, DEFAULT_PKG_CONCURRENCY_LIMIT_EJ)));
- mPkgConcurrencyLimitRegular = Math.max(1, Math.min(MAX_JOB_CONTEXTS_COUNT,
+ mPkgConcurrencyLimitRegular = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT,
properties.getInt(
KEY_PKG_CONCURRENCY_LIMIT_REGULAR, DEFAULT_PKG_CONCURRENCY_LIMIT_REGULAR)));
}
@@ -1492,6 +1595,13 @@ class JobConcurrencyManager {
jsc.dumpLocked(pw, nowElapsed);
}
pw.decreaseIndent();
+
+ if (mNumDroppedContexts > 0) {
+ pw.println();
+ pw.print("Dropped ");
+ pw.print(mNumDroppedContexts);
+ pw.println(" contexts");
+ }
}
public void dumpProtoLocked(ProtoOutputStream proto, long tag, long now, long nowRealtime) {
@@ -1600,7 +1710,7 @@ class JobConcurrencyManager {
WorkTypeConfig(@NonNull String configIdentifier, int defaultMaxTotal,
List<Pair<Integer, Integer>> defaultMin, List<Pair<Integer, Integer>> defaultMax) {
mConfigIdentifier = configIdentifier;
- mDefaultMaxTotal = mMaxTotal = Math.min(defaultMaxTotal, MAX_JOB_CONTEXTS_COUNT);
+ mDefaultMaxTotal = mMaxTotal = Math.min(defaultMaxTotal, STANDARD_CONCURRENCY_LIMIT);
int numReserved = 0;
for (int i = defaultMin.size() - 1; i >= 0; --i) {
mDefaultMinReservedSlots.put(defaultMin.get(i).first, defaultMin.get(i).second);
@@ -1621,8 +1731,8 @@ class JobConcurrencyManager {
}
void update(@NonNull DeviceConfig.Properties properties) {
- // Ensure total in the range [1, MAX_JOB_CONTEXTS_COUNT].
- mMaxTotal = Math.max(1, Math.min(MAX_JOB_CONTEXTS_COUNT,
+ // Ensure total in the range [1, STANDARD_CONCURRENCY_LIMIT].
+ mMaxTotal = Math.max(1, Math.min(STANDARD_CONCURRENCY_LIMIT,
properties.getInt(KEY_PREFIX_MAX_TOTAL + mConfigIdentifier, mDefaultMaxTotal)));
mMaxAllowedSlots.clear();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index fd7d8aa75882..b25832c7d521 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -159,8 +159,6 @@ public class JobSchedulerService extends com.android.server.SystemService
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
public static final boolean DEBUG_STANDBY = DEBUG || false;
- /** The maximum number of concurrent jobs we run at one time. */
- static final int MAX_JOB_CONTEXTS_COUNT = 16;
/** The maximum number of jobs that we allow an app to schedule */
private static final int MAX_JOBS_PER_APP = 150;
/** The number of the most recently completed jobs to keep track of for debugging purposes. */
@@ -1423,6 +1421,7 @@ public class JobSchedulerService extends com.android.server.SystemService
for (int c = 0; c < mControllers.size(); ++c) {
mControllers.get(c).onUidBiasChangedLocked(uid, prevBias, newBias);
}
+ mConcurrencyManager.onUidBiasChangedLocked(prevBias, newBias);
}
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
index 54e0a4c6663c..2a79ec4587fc 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java
@@ -751,7 +751,8 @@ public final class JobServiceContext implements ServiceConnection {
}
}
mParams.setStopReason(stopReasonCode, internalStopReasonCode, debugReason);
- if (internalStopReasonCode == JobParameters.INTERNAL_STOP_REASON_PREEMPT) {
+ if (stopReasonCode == JobParameters.STOP_REASON_PREEMPT) {
+ // Only preserve the UID when we're preempting the job for another one of the same UID.
mPreferredUid = mRunningJob != null ? mRunningJob.getUid() : NO_PREFERRED_UID;
}
handleCancelLocked(debugReason);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index b3e81cb89e52..fdcd2fc82ecc 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -297,9 +297,9 @@ public final class QuotaController extends StateController {
private final SparseBooleanArray mForegroundUids = new SparseBooleanArray();
/**
- * List of jobs that started while the UID was in the TOP state. There will be no more than
- * 16 ({@link JobSchedulerService#MAX_JOB_CONTEXTS_COUNT}) running at once, so an ArraySet is
- * fine.
+ * List of jobs that started while the UID was in the TOP state. There will usually be no more
+ * than {@value JobConcurrencyManager#MAX_STANDARD_JOB_CONCURRENCY} running at once, so an
+ * ArraySet is fine.
*/
private final ArraySet<JobStatus> mTopStartedJobs = new ArraySet<>();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java
index fd6aa7a1d282..223091a27ee1 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TareController.java
@@ -289,9 +289,9 @@ public class TareController extends StateController {
};
/**
- * List of jobs that started while the UID was in the TOP state. There will be no more than
- * 16 ({@link JobSchedulerService#MAX_JOB_CONTEXTS_COUNT}) running at once, so an ArraySet is
- * fine.
+ * List of jobs that started while the UID was in the TOP state. There will usually be no more
+ * than {@value JobConcurrencyManager#MAX_STANDARD_JOB_CONCURRENCY} running at once, so an
+ * ArraySet is fine.
*/
@GuardedBy("mLock")
private final ArraySet<JobStatus> mTopStartedJobs = new ArraySet<>();
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index b520102b2830..fde59ea1e5f3 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -1309,7 +1309,7 @@ public class AppStandbyController
return STANDBY_BUCKET_WORKING_SET;
}
- if (mInjector.hasScheduleExactAlarm(packageName, UserHandle.getUid(userId, appId))) {
+ if (mInjector.hasExactAlarmPermission(packageName, UserHandle.getUid(userId, appId))) {
return STANDBY_BUCKET_WORKING_SET;
}
}
@@ -2326,8 +2326,8 @@ public class AppStandbyController
return mWellbeingApp != null && mWellbeingApp.equals(packageName);
}
- boolean hasScheduleExactAlarm(String packageName, int uid) {
- return mAlarmManagerInternal.hasScheduleExactAlarm(packageName, uid);
+ boolean hasExactAlarmPermission(String packageName, int uid) {
+ return mAlarmManagerInternal.hasExactAlarmPermission(packageName, uid);
}
void updatePowerWhitelistCache() {
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index f9317eba4e27..968be3e20791 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -1425,12 +1425,17 @@ void BootAnimation::drawTexturedQuad(float xStart, float yStart, float width, fl
void BootAnimation::initDynamicColors() {
for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) {
- parseColorDecimalString(
- android::base::GetProperty("persist.bootanim.color" + std::to_string(i + 1), ""),
+ const auto syspropName = "persist.bootanim.color" + std::to_string(i + 1);
+ const auto syspropValue = android::base::GetProperty(syspropName, "");
+ if (syspropValue != "") {
+ SLOGI("Loaded dynamic color: %s -> %s", syspropName.c_str(), syspropValue.c_str());
+ mDynamicColorsApplied = true;
+ }
+ parseColorDecimalString(syspropValue,
mAnimation->endColors[i], mAnimation->startColors[i]);
}
glUseProgram(mImageShader);
- SLOGI("[BootAnimation] Dynamically coloring boot animation.");
+ SLOGI("Dynamically coloring boot animation. Sysprops loaded? %i", mDynamicColorsApplied);
for (int i = 0; i < DYNAMIC_COLOR_COUNT; i++) {
float *startColor = mAnimation->startColors[i];
float *endColor = mAnimation->endColors[i];
@@ -1465,6 +1470,11 @@ bool BootAnimation::playAnimation(const Animation& animation) {
continue; //to next part
}
+ if (animation.dynamicColoringEnabled && part.useDynamicColoring && !mDynamicColorsApplied) {
+ SLOGD("Trying to load dynamic color sysprops.");
+ initDynamicColors();
+ }
+
// process the part not only while the count allows but also if already fading
for (int r=0 ; !part.count || r<part.count || fadedFramesCount > 0 ; r++) {
if (shouldStopPlayingPart(part, fadedFramesCount, lastDisplayedProgress)) break;
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 4c378cbc48bd..a136ad0a90f2 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -228,6 +228,7 @@ private:
bool mTimeIsAccurate;
bool mTimeFormat12Hour;
bool mShuttingDown;
+ bool mDynamicColorsApplied = false;
String8 mZipFileName;
SortedVector<String8> mLoadedFiles;
sp<TimeCheckThread> mTimeCheckThread = nullptr;
diff --git a/core/api/current.txt b/core/api/current.txt
index 92c263624527..89ebf2773256 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9225,6 +9225,7 @@ package android.content {
field public static final int CLASSIFICATION_NOT_COMPLETE = 1; // 0x1
field public static final int CLASSIFICATION_NOT_PERFORMED = 2; // 0x2
field @NonNull public static final android.os.Parcelable.Creator<android.content.ClipDescription> CREATOR;
+ field public static final String EXTRA_IS_SENSITIVE = "android.content.extra.IS_SENSITIVE";
field public static final String MIMETYPE_TEXT_HTML = "text/html";
field public static final String MIMETYPE_TEXT_INTENT = "text/vnd.android.intent";
field public static final String MIMETYPE_TEXT_PLAIN = "text/plain";
@@ -37577,10 +37578,12 @@ package android.security {
public class KeyStoreException extends java.lang.Exception {
method public int getNumericErrorCode();
+ method public int getRetryPolicy();
method public boolean isSystemError();
method public boolean isTransientFailure();
method public boolean requiresUserAuthentication();
field public static final int ERROR_ATTESTATION_CHALLENGE_TOO_LARGE = 9; // 0x9
+ field public static final int ERROR_ATTESTATION_KEYS_UNAVAILABLE = 16; // 0x10
field public static final int ERROR_ID_ATTESTATION_FAILURE = 8; // 0x8
field public static final int ERROR_INCORRECT_USAGE = 13; // 0xd
field public static final int ERROR_INTERNAL_SYSTEM_ERROR = 4; // 0x4
@@ -37595,6 +37598,9 @@ package android.security {
field public static final int ERROR_PERMISSION_DENIED = 5; // 0x5
field public static final int ERROR_UNIMPLEMENTED = 12; // 0xc
field public static final int ERROR_USER_AUTHENTICATION_REQUIRED = 2; // 0x2
+ field public static final int RETRY_NEVER = 1; // 0x1
+ field public static final int RETRY_WHEN_CONNECTIVITY_AVAILABLE = 3; // 0x3
+ field public static final int RETRY_WITH_EXPONENTIAL_BACKOFF = 2; // 0x2
}
@Deprecated public final class KeyStoreParameter implements java.security.KeyStore.ProtectionParameter {
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 381314e36e66..df5dcda6eb42 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -3262,10 +3262,6 @@ package android.window {
field public static final int FEATURE_WINDOW_TOKENS = 2; // 0x2
}
- public interface OnBackInvokedDispatcher {
- field public static final long DISPATCH_BACK_INVOCATION_AHEAD_OF_TIME = 195946584L; // 0xbade858L
- }
-
public final class SplashScreenView extends android.widget.FrameLayout {
method @Nullable public android.view.View getBrandingView();
}
diff --git a/core/java/android/accessibilityservice/MagnificationConfig.java b/core/java/android/accessibilityservice/MagnificationConfig.java
index 74c91d6097c3..ddafb224a5cd 100644
--- a/core/java/android/accessibilityservice/MagnificationConfig.java
+++ b/core/java/android/accessibilityservice/MagnificationConfig.java
@@ -42,9 +42,9 @@ import java.lang.annotation.RetentionPolicy;
* </p>
*
* <p>
- * When the magnification config uses {@link #MAGNIFICATION_MODE_WINDOW}.
- * {@link AccessibilityService} will be able to control the activated window magnifier
- * on the display.
+ * When the magnification config uses {@link #MAGNIFICATION_MODE_WINDOW} and the platform
+ * supports {@link android.content.pm.PackageManager#FEATURE_WINDOW_MAGNIFICATION} feature.
+ * {@link AccessibilityService} will be able to control window magnifier on the display.
* </p>
*
* <p>
@@ -57,9 +57,12 @@ public final class MagnificationConfig implements Parcelable {
/** The controlling magnification mode. It controls the activated magnifier. */
public static final int MAGNIFICATION_MODE_DEFAULT = 0;
- /** The controlling magnification mode. It controls fullscreen magnifier. */
+ /** The controlling magnification mode. It controls full-screen magnifier. */
public static final int MAGNIFICATION_MODE_FULLSCREEN = 1;
- /** The controlling magnification mode. It controls window magnifier. */
+ /**
+ * The controlling magnification mode. It is valid if the platform supports
+ * {@link android.content.pm.PackageManager#FEATURE_WINDOW_MAGNIFICATION} feature.
+ */
public static final int MAGNIFICATION_MODE_WINDOW = 2;
/** @hide */
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 5e521b03f6e3..893dc2f6ace4 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -1209,7 +1209,9 @@ public final class UiAutomation {
* @see android.view.WindowAnimationFrameStats
* @see #getWindowAnimationFrameStats()
* @see android.R.styleable#WindowAnimation
- * @deprecated animation-frames are no-longer used.
+ * @deprecated animation-frames are no-longer used. Use Shared
+ * <a href="https://perfetto.dev/docs/data-sources/frametimeline">FrameTimeline</a>
+ * jank metrics instead.
*/
@Deprecated
public void clearWindowAnimationFrameStats() {
diff --git a/core/java/android/app/WindowConfiguration.java b/core/java/android/app/WindowConfiguration.java
index 5c1ab3879487..e502ba03bf8e 100644
--- a/core/java/android/app/WindowConfiguration.java
+++ b/core/java/android/app/WindowConfiguration.java
@@ -222,9 +222,6 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
})
public @interface WindowConfig {}
- /** @hide */
- public static final int PINNED_WINDOWING_MODE_ELEVATION_IN_DIP = 5;
-
@UnsupportedAppUsage
public WindowConfiguration() {
unset();
diff --git a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
index 3b15bcb9846d..0d9ecfdfe8f6 100644
--- a/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
+++ b/core/java/android/app/ambientcontext/IAmbientContextManager.aidl
@@ -25,7 +25,7 @@ import android.os.RemoteCallback;
*
* @hide
*/
-oneway interface IAmbientContextManager {
+interface IAmbientContextManager {
void registerObserver(in AmbientContextEventRequest request,
in PendingIntent resultPendingIntent,
in RemoteCallback statusCallback);
@@ -33,4 +33,4 @@ oneway interface IAmbientContextManager {
void queryServiceStatus(in int[] eventTypes, in String callingPackage,
in RemoteCallback statusCallback);
void startConsentActivity(in int[] eventTypes, in String callingPackage);
-} \ No newline at end of file
+}
diff --git a/core/java/android/companion/virtual/IVirtualDevice.aidl b/core/java/android/companion/virtual/IVirtualDevice.aidl
index e2859998efd4..8cfbf2faee67 100644
--- a/core/java/android/companion/virtual/IVirtualDevice.aidl
+++ b/core/java/android/companion/virtual/IVirtualDevice.aidl
@@ -17,7 +17,8 @@
package android.companion.virtual;
import android.app.PendingIntent;
-import android.companion.virtual.audio.IAudioSessionCallback;
+import android.companion.virtual.audio.IAudioConfigChangedCallback;
+import android.companion.virtual.audio.IAudioRoutingCallback;
import android.graphics.Point;
import android.graphics.PointF;
import android.hardware.input.VirtualKeyEvent;
@@ -51,7 +52,8 @@ interface IVirtualDevice {
*/
void onAudioSessionStarting(
int displayId,
- IAudioSessionCallback callback);
+ IAudioRoutingCallback routingCallback,
+ IAudioConfigChangedCallback configChangedCallback);
void onAudioSessionEnded();
diff --git a/core/java/android/companion/virtual/audio/IAudioSessionCallback.aidl b/core/java/android/companion/virtual/audio/IAudioConfigChangedCallback.aidl
index e22ce148a9be..47b5e940b27a 100644
--- a/core/java/android/companion/virtual/audio/IAudioSessionCallback.aidl
+++ b/core/java/android/companion/virtual/audio/IAudioConfigChangedCallback.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * Copyright (C) 2022 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.
@@ -20,15 +20,11 @@ import android.media.AudioPlaybackConfiguration;
import android.media.AudioRecordingConfiguration;
/**
- * Callback to control audio rerouting, notify playback and recording state of applications running
- * on virtual device.
+ * Callback to notify playback and recording state of applications running on virtual device.
*
* @hide
*/
-oneway interface IAudioSessionCallback {
-
- /** Updates the set of applications that need to have their audio rerouted. */
- void onAppsNeedingAudioRoutingChanged(in int[] appUids);
+oneway interface IAudioConfigChangedCallback {
/**
* Called whenever the playback configuration of applications running on virtual device has
diff --git a/core/java/android/companion/virtual/audio/IAudioRoutingCallback.aidl b/core/java/android/companion/virtual/audio/IAudioRoutingCallback.aidl
new file mode 100644
index 000000000000..a424d62266c9
--- /dev/null
+++ b/core/java/android/companion/virtual/audio/IAudioRoutingCallback.aidl
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.companion.virtual.audio;
+
+/**
+ * Callback to control audio rerouting for applications running on virtual device.
+ *
+ * @hide
+ */
+oneway interface IAudioRoutingCallback {
+
+ /** Updates the set of applications that need to have their audio rerouted. */
+ void onAppsNeedingAudioRoutingChanged(in int[] appUids);
+}
diff --git a/core/java/android/companion/virtual/audio/VirtualAudioDevice.java b/core/java/android/companion/virtual/audio/VirtualAudioDevice.java
index 3f7299fbb09e..0db7b5fe8289 100644
--- a/core/java/android/companion/virtual/audio/VirtualAudioDevice.java
+++ b/core/java/android/companion/virtual/audio/VirtualAudioDevice.java
@@ -76,8 +76,8 @@ public final class VirtualAudioDevice implements Closeable {
* @hide
*/
public VirtualAudioDevice(Context context, IVirtualDevice virtualDevice,
- VirtualDisplay virtualDisplay, Executor executor,
- AudioConfigurationChangeCallback callback) {
+ @NonNull VirtualDisplay virtualDisplay, @Nullable Executor executor,
+ @Nullable AudioConfigurationChangeCallback callback) {
mContext = context;
mVirtualDevice = virtualDevice;
mVirtualDisplay = virtualDisplay;
@@ -105,7 +105,8 @@ public final class VirtualAudioDevice implements Closeable {
try {
mVirtualDevice.onAudioSessionStarting(mVirtualDisplay.getDisplay().getDisplayId(),
- /* callback= */ mOngoingSession);
+ /* routingCallback= */ mOngoingSession,
+ /* configChangedCallback= */ mOngoingSession.getAudioConfigChangedListener());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -135,7 +136,8 @@ public final class VirtualAudioDevice implements Closeable {
try {
mVirtualDevice.onAudioSessionStarting(mVirtualDisplay.getDisplay().getDisplayId(),
- /* callback= */ mOngoingSession);
+ /* routingCallback= */ mOngoingSession,
+ /* configChangedCallback= */ mOngoingSession.getAudioConfigChangedListener());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/companion/virtual/audio/VirtualAudioSession.java b/core/java/android/companion/virtual/audio/VirtualAudioSession.java
index 524f6e2ab063..321a1c57643b 100644
--- a/core/java/android/companion/virtual/audio/VirtualAudioSession.java
+++ b/core/java/android/companion/virtual/audio/VirtualAudioSession.java
@@ -50,16 +50,14 @@ import java.util.concurrent.Executor;
* @hide
*/
@VisibleForTesting
-public final class VirtualAudioSession extends IAudioSessionCallback.Stub implements
+public final class VirtualAudioSession extends IAudioRoutingCallback.Stub implements
UserRestrictionsCallback, Closeable {
private static final String TAG = "VirtualAudioSession";
private final Context mContext;
private final UserRestrictionsDetector mUserRestrictionsDetector;
- /** The {@link Executor} for sending {@link AudioConfigurationChangeCallback} to the caller */
- private final Executor mExecutor;
@Nullable
- private final AudioConfigurationChangeCallback mCallback;
+ private final AudioConfigChangedCallback mAudioConfigChangedCallback;
private final Object mLock = new Object();
@GuardedBy("mLock")
private final IntArray mReroutedAppUids = new IntArray();
@@ -73,13 +71,44 @@ public final class VirtualAudioSession extends IAudioSessionCallback.Stub implem
@GuardedBy("mLock")
private AudioInjection mAudioInjection;
+ /**
+ * Class to receive {@link IAudioConfigChangedCallback} callbacks from service.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public static final class AudioConfigChangedCallback extends IAudioConfigChangedCallback.Stub {
+ private final Executor mExecutor;
+ private final AudioConfigurationChangeCallback mCallback;
+
+ AudioConfigChangedCallback(Context context, Executor executor,
+ AudioConfigurationChangeCallback callback) {
+ mExecutor = executor != null ? executor : context.getMainExecutor();
+ mCallback = callback;
+ }
+
+ @Override
+ public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
+ if (mCallback != null) {
+ mExecutor.execute(() -> mCallback.onPlaybackConfigChanged(configs));
+ }
+ }
+
+ @Override
+ public void onRecordingConfigChanged(List<AudioRecordingConfiguration> configs) {
+ if (mCallback != null) {
+ mExecutor.execute(() -> mCallback.onRecordingConfigChanged(configs));
+ }
+ }
+ }
+
@VisibleForTesting
public VirtualAudioSession(Context context,
@Nullable AudioConfigurationChangeCallback callback, @Nullable Executor executor) {
mContext = context;
mUserRestrictionsDetector = new UserRestrictionsDetector(context);
- mCallback = callback;
- mExecutor = executor != null ? executor : context.getMainExecutor();
+ mAudioConfigChangedCallback = callback == null ? null : new AudioConfigChangedCallback(
+ context, executor, callback);
}
/**
@@ -132,6 +161,13 @@ public final class VirtualAudioSession extends IAudioSessionCallback.Stub implem
/** @hide */
@VisibleForTesting
@Nullable
+ public AudioConfigChangedCallback getAudioConfigChangedListener() {
+ return mAudioConfigChangedCallback;
+ }
+
+ /** @hide */
+ @VisibleForTesting
+ @Nullable
public AudioCapture getAudioCapture() {
synchronized (mLock) {
return mAudioCapture;
@@ -263,20 +299,6 @@ public final class VirtualAudioSession extends IAudioSessionCallback.Stub implem
}
}
- @Override
- public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
- if (mCallback != null) {
- mExecutor.execute(() -> mCallback.onPlaybackConfigChanged(configs));
- }
- }
-
- @Override
- public void onRecordingConfigChanged(List<AudioRecordingConfiguration> configs) {
- if (mCallback != null) {
- mExecutor.execute(() -> mCallback.onRecordingConfigChanged(configs));
- }
- }
-
/** @hide */
@VisibleForTesting
public IntArray getReroutedAppUids() {
diff --git a/core/java/android/content/ClipDescription.java b/core/java/android/content/ClipDescription.java
index 2ecd71bc1f06..bf466116009b 100644
--- a/core/java/android/content/ClipDescription.java
+++ b/core/java/android/content/ClipDescription.java
@@ -134,6 +134,26 @@ public class ClipDescription implements Parcelable {
public static final String EXTRA_LOGGING_INSTANCE_ID =
"android.intent.extra.LOGGING_INSTANCE_ID";
+ /**
+ * Indicates that a ClipData contains potentially sensitive information, such as a
+ * password or credit card number.
+ * <p>
+ * Type: boolean
+ * </p>
+ * <p>
+ * This extra can be used to indicate that a ClipData contains sensitive information that
+ * should be redacted or hidden from view until a user takes explicit action to reveal it
+ * (e.g., by pasting).
+ * </p>
+ * <p>
+ * Adding this extra does not change clipboard behavior or add additional security to
+ * the ClipData. Its purpose is essentially a rendering hint from the source application,
+ * asking that the data within be obfuscated or redacted, unless the user has taken action
+ * to make it visible.
+ * </p>
+ */
+ public static final String EXTRA_IS_SENSITIVE = "android.content.extra.IS_SENSITIVE";
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(value =
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 227ac1a02890..a90f6d625c51 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4188,6 +4188,8 @@ public abstract class PackageManager {
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device
* supports window magnification.
+ *
+ * @see android.accessibilityservice.MagnificationConfig#MAGNIFICATION_MODE_WINDOW
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_WINDOW_MAGNIFICATION =
diff --git a/core/java/android/os/OWNERS b/core/java/android/os/OWNERS
index 8e5ed8f6e578..1f3108a1f04b 100644
--- a/core/java/android/os/OWNERS
+++ b/core/java/android/os/OWNERS
@@ -66,3 +66,6 @@ per-file *UpdateEngine* = file:/platform/system/update_engine:/OWNERS
# VINTF
per-file Vintf* = file:/platform/system/libvintf:/OWNERS
+
+# Tracing
+per-file Trace.java = file:/TRACE_OWNERS
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index a4f6004a288a..ac2156e9e46e 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -136,6 +136,12 @@ public final class Trace {
@FastNative
private static native void nativeAsyncTraceEnd(long tag, String name, int cookie);
@FastNative
+ private static native void nativeAsyncTraceForTrackBegin(long tag,
+ String trackName, String name, int cookie);
+ @FastNative
+ private static native void nativeAsyncTraceForTrackEnd(long tag,
+ String trackName, String name, int cookie);
+ @FastNative
private static native void nativeInstant(long tag, String name);
@FastNative
private static native void nativeInstantForTrack(long tag, String trackName, String name);
@@ -271,6 +277,47 @@ public final class Trace {
}
}
+
+ /**
+ * Writes a trace message to indicate that a given section of code has
+ * begun. Must be followed by a call to {@link #asyncTraceForTrackEnd} using the same
+ * tag. This function operates exactly like {@link #asyncTraceBegin(long, String, int)},
+ * except with the inclusion of a track name argument for where this method should appear.
+ *
+ * @param traceTag The trace tag.
+ * @param trackName The track where the event should appear in the trace.
+ * @param methodName The method name to appear in the trace.
+ * @param cookie Unique identifier for distinguishing simultaneous events
+ *
+ * @hide
+ */
+ public static void asyncTraceForTrackBegin(long traceTag,
+ @NonNull String trackName, @NonNull String methodName, int cookie) {
+ if (isTagEnabled(traceTag)) {
+ nativeAsyncTraceForTrackBegin(traceTag, trackName, methodName, cookie);
+ }
+ }
+
+ /**
+ * Writes a trace message to indicate that the current method has ended.
+ * Must be called exactly once for each call to
+ * {@link #asyncTraceForTrackBegin(long, String, String, int)}
+ * using the same tag, track name, name and cookie.
+ *
+ * @param traceTag The trace tag.
+ * @param trackName The track where the event should appear in the trace.
+ * @param methodName The method name to appear in the trace.
+ * @param cookie Unique identifier for distinguishing simultaneous events
+ *
+ * @hide
+ */
+ public static void asyncTraceForTrackEnd(long traceTag,
+ @NonNull String trackName, @NonNull String methodName, int cookie) {
+ if (isTagEnabled(traceTag)) {
+ nativeAsyncTraceForTrackEnd(traceTag, trackName, methodName, cookie);
+ }
+ }
+
/**
* Writes a trace message to indicate that a given section of code was invoked.
*
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 7dc4f22000b8..9591e4125ee7 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -8093,14 +8093,17 @@ public final class ViewRootImpl implements ViewParent,
private void setFrame(Rect frame) {
mWinFrame.set(frame);
+ final WindowConfiguration winConfig = getConfiguration().windowConfiguration;
+ mPendingBackDropFrame.set(mPendingDragResizing && !winConfig.useWindowFrameForBackdrop()
+ ? winConfig.getMaxBounds()
+ : frame);
// Surface position is now inherited from parent, and BackdropFrameRenderer uses backdrop
// frame to position content. Thus, we just keep the size of backdrop frame, and remove the
// offset to avoid double offset from display origin.
- mPendingBackDropFrame.set(frame);
mPendingBackDropFrame.offsetTo(0, 0);
mInsetsController.onFrameChanged(mOverrideInsetsFrame != null ?
- mOverrideInsetsFrame : frame);
+ mOverrideInsetsFrame : frame);
}
/**
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index cde1cc704f92..ba3417980a3d 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -517,6 +517,13 @@ public final class WindowInsets {
/**
* Returns the {@link Rect} of the maximum bounds of the system privacy indicator, for the
* current orientation, in relative coordinates, or null if the bounds have not been loaded yet.
+ * <p>
+ * The privacy indicator bounds are determined by SystemUI, and subsequently loaded once the
+ * StatusBar window has been created and attached. The bounds for all rotations are calculated
+ * and loaded at once, and this value is only expected to ever change on display or font scale
+ * changes. As long as there is a StatusBar window, this value should not be expected to be
+ * null.
+ * <p>
* The privacy indicator shows over apps when an app uses the microphone or camera permissions,
* while an app is in immersive mode.
*
diff --git a/core/java/android/view/translation/UiTranslationManager.java b/core/java/android/view/translation/UiTranslationManager.java
index 01acdfec6c27..9fc7b07200ae 100644
--- a/core/java/android/view/translation/UiTranslationManager.java
+++ b/core/java/android/view/translation/UiTranslationManager.java
@@ -163,7 +163,6 @@ public final class UiTranslationManager {
/**
* @removed Use {@link #startTranslation(TranslationSpec, TranslationSpec, List, ActivityId,
* UiTranslationSpec)} instead.
- *
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION)
@@ -180,13 +179,13 @@ public final class UiTranslationManager {
/**
* Request ui translation for a given Views.
*
- * @param sourceSpec {@link TranslationSpec} for the data to be translated.
- * @param targetSpec {@link TranslationSpec} for the translated data.
- * @param viewIds A list of the {@link View}'s {@link AutofillId} which needs to be translated
- * @param activityId the identifier for the Activity which needs ui translation
+ * @param sourceSpec {@link TranslationSpec} for the data to be translated.
+ * @param targetSpec {@link TranslationSpec} for the translated data.
+ * @param viewIds A list of the {@link View}'s {@link AutofillId} which needs to be
+ * translated
+ * @param activityId the identifier for the Activity which needs ui translation
* @param uiTranslationSpec configuration for translation of the specified views
* @throws IllegalArgumentException if the no {@link View}'s {@link AutofillId} in the list
- *
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION)
@@ -220,8 +219,7 @@ public final class UiTranslationManager {
*
* @param activityId the identifier for the Activity which needs ui translation
* @throws NullPointerException the activityId or
- * {@link android.app.assist.ActivityId#getToken()} is {@code null}
- *
+ * {@link android.app.assist.ActivityId#getToken()} is {@code null}
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION)
@@ -245,8 +243,7 @@ public final class UiTranslationManager {
*
* @param activityId the identifier for the Activity which needs ui translation
* @throws NullPointerException the activityId or
- * {@link android.app.assist.ActivityId#getToken()} is {@code null}
- *
+ * {@link android.app.assist.ActivityId#getToken()} is {@code null}
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION)
@@ -270,8 +267,7 @@ public final class UiTranslationManager {
*
* @param activityId the identifier for the Activity which needs ui translation
* @throws NullPointerException the activityId or
- * {@link android.app.assist.ActivityId#getToken()} is {@code null}
- *
+ * {@link android.app.assist.ActivityId#getToken()} is {@code null}
* @hide
*/
@RequiresPermission(android.Manifest.permission.MANAGE_UI_TRANSLATION)
@@ -290,20 +286,29 @@ public final class UiTranslationManager {
}
/**
- * Register for notifications of UI Translation state changes on the foreground activity. This
+ * Register for notifications of UI Translation state changes on the foreground Activity. This
* is available to the owning application itself and also the current input method.
* <p>
* The application whose UI is being translated can use this to customize the UI Translation
* behavior in ways that aren't made easy by methods like
* {@link View#onCreateViewTranslationRequest(int[], Consumer)}.
- *
* <p>
* Input methods can use this to offer complementary features to UI Translation; for example,
* enabling outgoing message translation when the system is translating incoming messages in a
* communication app.
+ * <p>
+ * Starting from {@link android.os.Build.VERSION_CODES#TIRAMISU}, if Activities are already
+ * being translated when a callback is registered, methods on the callback will be invoked for
+ * each translated activity, depending on the state of translation:
+ * <ul>
+ * <li>If translation is <em>not</em> paused,
+ * {@link UiTranslationStateCallback#onStarted} will be invoked.</li>
+ * <li>If translation <em>is</em> paused, {@link UiTranslationStateCallback#onStarted}
+ * will first be invoked, followed by {@link UiTranslationStateCallback#onPaused}.</li>
+ * </ul>
*
* @param callback the callback to register for receiving the state change
- * notifications
+ * notifications
*/
public void registerUiTranslationStateCallback(
@NonNull @CallbackExecutor Executor executor,
@@ -355,9 +360,8 @@ public final class UiTranslationManager {
* called or Activity is destroyed.
*
* @param activityDestroyed if the ui translation is finished because of activity destroyed.
- * @param activityId the identifier for the Activity which needs ui translation
- * @param componentName the ui translated Activity componentName.
- *
+ * @param activityId the identifier for the Activity which needs ui translation
+ * @param componentName the ui translated Activity componentName.
* @hide
*/
public void onTranslationFinished(boolean activityDestroyed, ActivityId activityId,
diff --git a/core/java/android/window/OnBackInvokedDispatcher.java b/core/java/android/window/OnBackInvokedDispatcher.java
index 5eed8cde8c7c..c254a9df3b4c 100644
--- a/core/java/android/window/OnBackInvokedDispatcher.java
+++ b/core/java/android/window/OnBackInvokedDispatcher.java
@@ -21,9 +21,6 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
-import android.annotation.TestApi;
-import android.compat.annotation.ChangeId;
-import android.compat.annotation.EnabledSince;
import android.os.Build;
import java.lang.annotation.Retention;
@@ -38,23 +35,6 @@ import java.lang.annotation.RetentionPolicy;
* target (a.k.a. the callback to be invoked next), or its behavior.
*/
public interface OnBackInvokedDispatcher {
- /**
- * Enables dispatching the "back" action via {@link OnBackInvokedDispatcher}.
- *
- * When enabled, the following APIs are no longer invoked:
- * <ul>
- * <li> {@link android.app.Activity#onBackPressed}
- * <li> {@link android.app.Dialog#onBackPressed}
- * <li> {@link android.view.KeyEvent#KEYCODE_BACK} is no longer dispatched.
- * </ul>
- *
- * @hide
- */
- @TestApi
- @ChangeId
- @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
- long DISPATCH_BACK_INVOCATION_AHEAD_OF_TIME = 195946584L;
-
/** @hide */
String TAG = "OnBackInvokedDispatcher";
diff --git a/core/java/android/window/PictureInPictureSurfaceTransaction.java b/core/java/android/window/PictureInPictureSurfaceTransaction.java
index 2bf2f3193789..0a751c38cfff 100644
--- a/core/java/android/window/PictureInPictureSurfaceTransaction.java
+++ b/core/java/android/window/PictureInPictureSurfaceTransaction.java
@@ -47,6 +47,8 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
public final float mCornerRadius;
+ public final float mShadowRadius;
+
private final Rect mWindowCrop;
private PictureInPictureSurfaceTransaction(Parcel in) {
@@ -56,11 +58,12 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
in.readFloatArray(mFloat9);
mRotation = in.readFloat();
mCornerRadius = in.readFloat();
+ mShadowRadius = in.readFloat();
mWindowCrop = in.readTypedObject(Rect.CREATOR);
}
private PictureInPictureSurfaceTransaction(float alpha, @Nullable PointF position,
- @Nullable float[] float9, float rotation, float cornerRadius,
+ @Nullable float[] float9, float rotation, float cornerRadius, float shadowRadius,
@Nullable Rect windowCrop) {
mAlpha = alpha;
mPosition = position;
@@ -73,12 +76,14 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
mRotation = rotation;
}
mCornerRadius = cornerRadius;
+ mShadowRadius = shadowRadius;
mWindowCrop = (windowCrop == null) ? null : new Rect(windowCrop);
}
public PictureInPictureSurfaceTransaction(PictureInPictureSurfaceTransaction other) {
this(other.mAlpha, other.mPosition,
- other.mFloat9, other.mRotation, other.mCornerRadius, other.mWindowCrop);
+ other.mFloat9, other.mRotation, other.mCornerRadius, other.mShadowRadius,
+ other.mWindowCrop);
}
/** @return {@link Matrix} from {@link #mFloat9} */
@@ -93,6 +98,11 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
return mCornerRadius > 0;
}
+ /** @return {@code true} if this transaction contains setting shadow radius. */
+ public boolean hasShadowRadiusSet() {
+ return mShadowRadius > 0;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -103,13 +113,14 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
&& Arrays.equals(mFloat9, that.mFloat9)
&& Objects.equals(mRotation, that.mRotation)
&& Objects.equals(mCornerRadius, that.mCornerRadius)
+ && Objects.equals(mShadowRadius, that.mShadowRadius)
&& Objects.equals(mWindowCrop, that.mWindowCrop);
}
@Override
public int hashCode() {
return Objects.hash(mAlpha, mPosition, Arrays.hashCode(mFloat9),
- mRotation, mCornerRadius, mWindowCrop);
+ mRotation, mCornerRadius, mShadowRadius, mWindowCrop);
}
@Override
@@ -124,6 +135,7 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
out.writeFloatArray(mFloat9);
out.writeFloat(mRotation);
out.writeFloat(mCornerRadius);
+ out.writeFloat(mShadowRadius);
out.writeTypedObject(mWindowCrop, 0 /* flags */);
}
@@ -136,6 +148,7 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
+ " matrix=" + matrix.toShortString()
+ " rotation=" + mRotation
+ " cornerRadius=" + mCornerRadius
+ + " shadowRadius=" + mShadowRadius
+ " crop=" + mWindowCrop
+ ")";
}
@@ -156,6 +169,9 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
if (surfaceTransaction.hasCornerRadiusSet()) {
tx.setCornerRadius(surfaceControl, surfaceTransaction.mCornerRadius);
}
+ if (surfaceTransaction.hasShadowRadiusSet()) {
+ tx.setShadowRadius(surfaceControl, surfaceTransaction.mShadowRadius);
+ }
if (surfaceTransaction.mAlpha != NOT_SET) {
tx.setAlpha(surfaceControl, surfaceTransaction.mAlpha);
}
@@ -178,6 +194,7 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
private float[] mFloat9;
private float mRotation;
private float mCornerRadius = NOT_SET;
+ private float mShadowRadius = NOT_SET;
private Rect mWindowCrop;
public Builder setAlpha(float alpha) {
@@ -201,6 +218,11 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
return this;
}
+ public Builder setShadowRadius(float shadowRadius) {
+ mShadowRadius = shadowRadius;
+ return this;
+ }
+
public Builder setWindowCrop(@NonNull Rect windowCrop) {
mWindowCrop = new Rect(windowCrop);
return this;
@@ -208,7 +230,7 @@ public final class PictureInPictureSurfaceTransaction implements Parcelable {
public PictureInPictureSurfaceTransaction build() {
return new PictureInPictureSurfaceTransaction(mAlpha, mPosition,
- mFloat9, mRotation, mCornerRadius, mWindowCrop);
+ mFloat9, mRotation, mCornerRadius, mShadowRadius, mWindowCrop);
}
}
}
diff --git a/core/java/android/window/WindowOnBackInvokedDispatcher.java b/core/java/android/window/WindowOnBackInvokedDispatcher.java
index e0bee96002b8..8811116b25ad 100644
--- a/core/java/android/window/WindowOnBackInvokedDispatcher.java
+++ b/core/java/android/window/WindowOnBackInvokedDispatcher.java
@@ -18,7 +18,6 @@ package android.window;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.app.compat.CompatChanges;
import android.content.Context;
import android.os.Debug;
import android.os.Handler;
@@ -253,21 +252,20 @@ public class WindowOnBackInvokedDispatcher implements OnBackInvokedDispatcher {
* {@link OnBackInvokedCallback}.
*/
public static boolean isOnBackInvokedCallbackEnabled(@Nullable Context context) {
- // new back is enabled if the app targets T AND the feature flag is enabled AND the app
- // does not explicitly request legacy back.
- boolean targetsT = CompatChanges.isChangeEnabled(DISPATCH_BACK_INVOCATION_AHEAD_OF_TIME);
+ // new back is enabled if the feature flag is enabled AND the app does not explicitly
+ // request legacy back.
boolean featureFlagEnabled = IS_BACK_PREDICTABILITY_ENABLED;
// If the context is null, we assume true and fallback on the two other conditions.
- boolean appRequestsLegacy =
- context == null || !context.getApplicationInfo().isOnBackInvokedCallbackEnabled();
+ boolean appRequestsPredictiveBack =
+ context != null && context.getApplicationInfo().isOnBackInvokedCallbackEnabled();
if (DEBUG) {
- Log.d(TAG, TextUtils.formatSimple("App: %s isChangeEnabled=%s featureFlagEnabled=%s "
- + "onBackInvokedEnabled=%s",
+ Log.d(TAG, TextUtils.formatSimple("App: %s featureFlagEnabled=%s "
+ + "appRequestsPredictiveBack=%s",
context != null ? context.getApplicationInfo().packageName : "null context",
- targetsT, featureFlagEnabled, !appRequestsLegacy));
+ featureFlagEnabled, appRequestsPredictiveBack));
}
- return targetsT && featureFlagEnabled && !appRequestsLegacy;
+ return featureFlagEnabled && appRequestsPredictiveBack;
}
}
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index a316669aa516..88089b5b85f2 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -1158,9 +1158,7 @@ public class ChooserActivity extends ResolverActivity implements
-1);
// Action bar is user-independent, always start as primary
safelyStartActivityAsUser(ti, getPersonalProfileUserHandle());
- if (!mAwaitingDelegateResponse) {
- finish();
- }
+ finish();
}
);
b.setId(R.id.chooser_nearby_button);
@@ -1182,9 +1180,7 @@ public class ChooserActivity extends ResolverActivity implements
-1);
// Action bar is user-independent, always start as primary
safelyStartActivityAsUser(ti, getPersonalProfileUserHandle());
- if (!mAwaitingDelegateResponse) {
- finish();
- }
+ finish();
}
);
b.setId(R.id.chooser_edit_button);
@@ -2231,9 +2227,7 @@ public class ChooserActivity extends ResolverActivity implements
TargetInfo clonedTarget = selectedTarget.cloneFilledIn(matchingIntent, 0);
if (super.onTargetSelected(clonedTarget, false)) {
updateModelAndChooserCounts(clonedTarget);
- if (!mAwaitingDelegateResponse) {
- finish();
- }
+ finish();
return;
}
}
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 1815ca69a55c..ea8589bddabb 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -210,7 +210,7 @@ public class ResolverActivity extends Activity implements
private UserHandle mWorkProfileUserHandle;
- protected boolean mAwaitingDelegateResponse;
+
/**
* Get the string resource to be used as a label for the link to the resolver activity for an
@@ -328,86 +328,6 @@ public class ResolverActivity extends Activity implements
super.onCreate(savedInstanceState);
}
- /**
- * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
- * where we hand over to the unbundled chooser (while violating many of the invariants of a
- * typical ResolverActivity implementation). Subclasses running in this mode need to be able
- * to opt-out of the normal ResolverActivity behavior.
- *
- * TODO: this should be removed later on in the unbundling migration, when the springboard
- * activity no longer needs to derive from ResolverActivity. The hold-over design here is
- * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
- * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
- * implementations that depend on the invariants that are violated in the headless mode). If
- * necessary, we could instead consider using a springboard-only activity on the system side
- * immediately, which would delegate either to the unbundled chooser, or to a
- * (properly-inheriting) system ChooserActivity. This would have performance implications even
- * when the unbundling experiment is disabled.
- */
- protected void super_onRestart() {
- super.onRestart();
- }
-
- /**
- * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
- * where we hand over to the unbundled chooser (while violating many of the invariants of a
- * typical ResolverActivity implementation). Subclasses running in this mode need to be able
- * to opt-out of the normal ResolverActivity behavior.
- *
- * TODO: this should be removed later on in the unbundling migration, when the springboard
- * activity no longer needs to derive from ResolverActivity. The hold-over design here is
- * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
- * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
- * implementations that depend on the invariants that are violated in the headless mode). If
- * necessary, we could instead consider using a springboard-only activity on the system side
- * immediately, which would delegate either to the unbundled chooser, or to a
- * (properly-inheriting) system ChooserActivity. This would have performance implications even
- * when the unbundling experiment is disabled.
- */
- protected void super_onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- }
-
- /**
- * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
- * where we hand over to the unbundled chooser (while violating many of the invariants of a
- * typical ResolverActivity implementation). Subclasses running in this mode need to be able
- * to opt-out of the normal ResolverActivity behavior.
- *
- * TODO: this should be removed later on in the unbundling migration, when the springboard
- * activity no longer needs to derive from ResolverActivity. The hold-over design here is
- * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
- * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
- * implementations that depend on the invariants that are violated in the headless mode). If
- * necessary, we could instead consider using a springboard-only activity on the system side
- * immediately, which would delegate either to the unbundled chooser, or to a
- * (properly-inheriting) system ChooserActivity. This would have performance implications even
- * when the unbundling experiment is disabled.
- */
- protected void super_onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- }
-
- /**
- * Pass-through API to support {@link ChooserActivity} running in "headless springboard" mode
- * where we hand over to the unbundled chooser (while violating many of the invariants of a
- * typical ResolverActivity implementation). Subclasses running in this mode need to be able
- * to opt-out of the normal ResolverActivity behavior.
- *
- * TODO: this should be removed later on in the unbundling migration, when the springboard
- * activity no longer needs to derive from ResolverActivity. The hold-over design here is
- * <em>not</em> good practice (e.g. there could be other events that weren't anticipated as
- * requiring this kind of "pass-through" override, and so might fall back on ResolverActivity
- * implementations that depend on the invariants that are violated in the headless mode). If
- * necessary, we could instead consider using a springboard-only activity on the system side
- * immediately, which would delegate either to the unbundled chooser, or to a
- * (properly-inheriting) system ChooserActivity. This would have performance implications even
- * when the unbundling experiment is disabled.
- */
- public void super_onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- }
-
@Override
protected void onCreate(Bundle savedInstanceState) {
// Use a specialized prompt when we're handling the 'Home' app startActivity()
@@ -682,9 +602,7 @@ public class ResolverActivity extends Activity implements
mProfileSwitchMessage = null;
onTargetSelected(dri, false);
- if (!mAwaitingDelegateResponse) {
- finish();
- }
+ finish();
}
/**
@@ -974,7 +892,7 @@ public class ResolverActivity extends Activity implements
}
final Intent intent = getIntent();
if ((intent.getFlags() & FLAG_ACTIVITY_NEW_TASK) != 0 && !isVoiceInteraction()
- && !mResolvingHome && !mRetainInOnStop && !mAwaitingDelegateResponse) {
+ && !mResolvingHome && !mRetainInOnStop) {
// This resolver is in the unusual situation where it has been
// launched at the top of a new task. We don't let it be added
// to the recent tasks shown to the user, and we need to make sure
@@ -1143,9 +1061,7 @@ public class ResolverActivity extends Activity implements
mMultiProfilePagerAdapter.getActiveListAdapter().hasFilteredItem()
? MetricsProto.MetricsEvent.ACTION_HIDE_APP_DISAMBIG_APP_FEATURED
: MetricsProto.MetricsEvent.ACTION_HIDE_APP_DISAMBIG_NONE_FEATURED);
- if (!mAwaitingDelegateResponse) {
- finish();
- }
+ finish();
}
}
@@ -2365,9 +2281,7 @@ public class ResolverActivity extends Activity implements
.getItem(selections[0].getIndex());
if (ra.onTargetSelected(ti, false)) {
ra.mPickOptionRequest = null;
- if (!ra.mAwaitingDelegateResponse) {
- ra.finish();
- }
+ ra.finish();
}
}
}
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 0ada13a73ad2..f19bfc669997 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -514,9 +514,10 @@ public final class SystemUiDeviceConfigFlags {
"is_nearby_share_first_target_in_ranked_app";
/**
- * (boolean) Whether to enable the new unbundled "delegate chooser" implementation.
+ * (boolean) Whether to enable the new unbundled sharesheet
+ * (com.android.intentresolver.ChooserActivity).
*/
- public static final String USE_DELEGATE_CHOOSER = "use_delegate_chooser";
+ public static final String USE_UNBUNDLED_SHARESHEET = "use_unbundled_sharesheet";
/**
* (string) Name of the default QR code scanner activity. On the eligible devices this activity
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 89ac72255306..13ebe3c4dbb7 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -16,9 +16,7 @@
package com.android.internal.policy;
-import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
-import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.os.Build.VERSION_CODES.M;
import static android.os.Build.VERSION_CODES.N;
@@ -2549,9 +2547,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
// Convert the DP elevation into physical pixels.
elevation = dipToPx(elevation);
mElevationAdjustedForStack = true;
- } else if (windowingMode == WINDOWING_MODE_PINNED) {
- elevation = dipToPx(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP);
- mElevationAdjustedForStack = true;
} else {
mElevationAdjustedForStack = false;
}
diff --git a/core/jni/OWNERS b/core/jni/OWNERS
index 2a4f812eb1de..9e5f6ea666ba 100644
--- a/core/jni/OWNERS
+++ b/core/jni/OWNERS
@@ -59,6 +59,7 @@ per-file android_media_* = file:/media/java/android/media/OWNERS
per-file android_media_midi_* = file:/media/java/android/media/midi/OWNERS
per-file android_opengl_* = file:/opengl/java/android/opengl/OWNERS
per-file android_os_storage_* = file:/core/java/android/os/storage/OWNERS
+per-file android_os_Trace* = file:/TRACE_OWNERS
per-file android_se_* = file:/omapi/java/android/se/OWNERS
per-file android_security_* = file:/core/java/android/security/OWNERS
per-file android_view_* = file:/core/java/android/view/OWNERS
diff --git a/core/jni/android_hardware_input_InputApplicationHandle.cpp b/core/jni/android_hardware_input_InputApplicationHandle.cpp
index 24d35316ef20..eab4e1d744cf 100644
--- a/core/jni/android_hardware_input_InputApplicationHandle.cpp
+++ b/core/jni/android_hardware_input_InputApplicationHandle.cpp
@@ -105,10 +105,11 @@ std::shared_ptr<InputApplicationHandle> android_view_InputApplicationHandle_getH
jobject android_view_InputApplicationHandle_fromInputApplicationInfo(
JNIEnv* env, gui::InputApplicationInfo inputApplicationInfo) {
- jobject binderObject = javaObjectForIBinder(env, inputApplicationInfo.token);
+ ScopedLocalRef<jobject> binderObject(env,
+ javaObjectForIBinder(env, inputApplicationInfo.token));
ScopedLocalRef<jstring> name(env, env->NewStringUTF(inputApplicationInfo.name.data()));
return env->NewObject(gInputApplicationHandleClassInfo.clazz,
- gInputApplicationHandleClassInfo.ctor, binderObject, name.get(),
+ gInputApplicationHandleClassInfo.ctor, binderObject.get(), name.get(),
inputApplicationInfo.dispatchingTimeoutMillis);
}
diff --git a/core/jni/android_hardware_input_InputWindowHandle.cpp b/core/jni/android_hardware_input_InputWindowHandle.cpp
index db92310f2a26..484d92820b86 100644
--- a/core/jni/android_hardware_input_InputWindowHandle.cpp
+++ b/core/jni/android_hardware_input_InputWindowHandle.cpp
@@ -261,8 +261,8 @@ jobject android_view_InputWindowHandle_fromWindowInfo(JNIEnv* env, gui::WindowIn
}
LOG_ALWAYS_FATAL_IF(inputWindowHandle == nullptr,
"Failed to create new InputWindowHandle object.");
- env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.token,
- javaObjectForIBinder(env, windowInfo.token));
+ ScopedLocalRef<jobject> token(env, javaObjectForIBinder(env, windowInfo.token));
+ env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.token, token.get());
ScopedLocalRef<jstring> name(env, env->NewStringUTF(windowInfo.name.data()));
env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.name, name.get());
env->SetIntField(inputWindowHandle, gInputWindowHandleClassInfo.layoutParamsFlags,
@@ -317,8 +317,9 @@ jobject android_view_InputWindowHandle_fromWindowInfo(JNIEnv* env, gui::WindowIn
ScopedLocalRef<jobject> matrixObj(env, AMatrix_newInstance(env, transformVals));
env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.transform, matrixObj.get());
+ ScopedLocalRef<jobject> windowToken(env, javaObjectForIBinder(env, windowInfo.windowToken));
env->SetObjectField(inputWindowHandle, gInputWindowHandleClassInfo.windowToken,
- javaObjectForIBinder(env, windowInfo.windowToken));
+ windowToken.get());
return inputWindowHandle;
}
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
index 85fd5d99e473..734b6ca47660 100644
--- a/core/jni/android_os_Trace.cpp
+++ b/core/jni/android_os_Trace.cpp
@@ -82,6 +82,26 @@ static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass,
});
}
+static void android_os_Trace_nativeAsyncTraceForTrackBegin(JNIEnv* env, jclass, jlong tag,
+ jstring trackStr, jstring nameStr,
+ jint cookie) {
+ withString(env, trackStr, [env, tag, nameStr, cookie](char* track) {
+ withString(env, nameStr, [tag, track, cookie](char* name) {
+ atrace_async_for_track_begin(tag, track, name, cookie);
+ });
+ });
+}
+
+static void android_os_Trace_nativeAsyncTraceForTrackEnd(JNIEnv* env, jclass, jlong tag,
+ jstring trackStr, jstring nameStr,
+ jint cookie) {
+ withString(env, trackStr, [env, tag, nameStr, cookie](char* track) {
+ withString(env, nameStr, [tag, track, cookie](char* name) {
+ atrace_async_for_track_end(tag, track, name, cookie);
+ });
+ });
+}
+
static void android_os_Trace_nativeSetAppTracingAllowed(JNIEnv*, jclass, jboolean allowed) {
atrace_update_tags();
}
@@ -132,6 +152,12 @@ static const JNINativeMethod gTraceMethods[] = {
{ "nativeAsyncTraceEnd",
"(JLjava/lang/String;I)V",
(void*)android_os_Trace_nativeAsyncTraceEnd },
+ { "nativeAsyncTraceForTrackBegin",
+ "(JLjava/lang/String;Ljava/lang/String;I)V",
+ (void*)android_os_Trace_nativeAsyncTraceForTrackBegin },
+ { "nativeAsyncTraceForTrackEnd",
+ "(JLjava/lang/String;Ljava/lang/String;I)V",
+ (void*)android_os_Trace_nativeAsyncTraceForTrackEnd },
{ "nativeInstant",
"(JLjava/lang/String;)V",
(void*)android_os_Trace_nativeInstant },
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index e1b7a0c08cb3..fa58a71f25b9 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2729,6 +2729,11 @@
<!-- Whether force to enable telephony new data stack or not -->
<bool name="config_force_enable_telephony_new_data_stack">true</bool>
+ <!-- Whether to adopt the predefined handover policies for IWLAN.
+ {@see CarrierConfigManager#KEY_IWLAN_HANDOVER_POLICY_STRING_ARRAY}
+ -->
+ <bool name="config_enable_iwlan_handover_policy">true</bool>
+
<!-- Whether WiFi display is supported by this device.
There are many prerequisites for this feature to work correctly.
Here are a few of them:
@@ -4105,12 +4110,6 @@
<!-- Intent extra key for the event code int array while requesting ambient context consent. -->
<string translatable="false" name="config_ambientContextEventArrayExtraKey"></string>
- <!-- The component name for the system-wide captions service.
- This service must be trusted, as it controls part of the UI of the volume bar.
- Example: "com.android.captions/.SystemCaptionsService"
- -->
- <string name="config_defaultSystemCaptionsService" translatable="false"></string>
-
<!-- The component name for the system-wide captions manager service.
This service must be trusted, as the system binds to it and keeps it running.
Example: "com.android.captions/.SystemCaptionsManagerService"
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 94c9a122ee75..cefba56b957e 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -475,6 +475,7 @@
<java-symbol type="array" name="config_network_type_tcp_buffers" />
<java-symbol type="string" name="config_tcp_buffers" />
<java-symbol type="bool" name="config_force_enable_telephony_new_data_stack" />
+ <java-symbol type="bool" name="config_enable_iwlan_handover_policy" />
<java-symbol type="integer" name="config_volte_replacement_rat"/>
<java-symbol type="integer" name="config_valid_wappush_index" />
<java-symbol type="integer" name="config_overrideHasPermanentMenuKey" />
@@ -3708,7 +3709,6 @@
<java-symbol type="string" name="config_defaultMusicRecognitionService" />
<java-symbol type="string" name="config_defaultAttentionService" />
<java-symbol type="string" name="config_defaultRotationResolverService" />
- <java-symbol type="string" name="config_defaultSystemCaptionsService" />
<java-symbol type="string" name="config_defaultSystemCaptionsManagerService" />
<java-symbol type="string" name="config_defaultAmbientContextDetectionService" />
<java-symbol type="string" name="config_defaultAmbientContextConsentComponent" />
diff --git a/core/tests/coretests/src/android/companion/virtual/audio/VirtualAudioSessionTest.java b/core/tests/coretests/src/android/companion/virtual/audio/VirtualAudioSessionTest.java
index 0e09d563c884..e025fae4b909 100644
--- a/core/tests/coretests/src/android/companion/virtual/audio/VirtualAudioSessionTest.java
+++ b/core/tests/coretests/src/android/companion/virtual/audio/VirtualAudioSessionTest.java
@@ -167,7 +167,7 @@ public class VirtualAudioSessionTest {
public void onPlaybackConfigChanged_sendsCallback() {
List<AudioPlaybackConfiguration> configs = new ArrayList<>();
- mVirtualAudioSession.onPlaybackConfigChanged(configs);
+ mVirtualAudioSession.getAudioConfigChangedListener().onPlaybackConfigChanged(configs);
verify(mCallback, timeout(2000)).onPlaybackConfigChanged(configs);
}
@@ -176,7 +176,7 @@ public class VirtualAudioSessionTest {
public void onRecordingConfigChanged_sendCallback() {
List<AudioRecordingConfiguration> configs = new ArrayList<>();
- mVirtualAudioSession.onRecordingConfigChanged(configs);
+ mVirtualAudioSession.getAudioConfigChangedListener().onRecordingConfigChanged(configs);
verify(mCallback, timeout(2000)).onRecordingConfigChanged(configs);
}
diff --git a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
index fb0880ce3521..bbaf0862f923 100644
--- a/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
+++ b/identity/java/android/security/identity/CredstoreIdentityCredentialStore.java
@@ -19,7 +19,10 @@ package android.security.identity;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
+import android.os.RemoteException;
import android.os.ServiceManager;
+import android.security.GenerateRkpKey;
+import android.security.keymaster.KeymasterDefs;
class CredstoreIdentityCredentialStore extends IdentityCredentialStore {
@@ -104,6 +107,16 @@ class CredstoreIdentityCredentialStore extends IdentityCredentialStore {
try {
IWritableCredential wc;
wc = mStore.createCredential(credentialName, docType);
+ try {
+ GenerateRkpKey keyGen = new GenerateRkpKey(mContext);
+ // We don't know what the security level is for the backing keymint, so go ahead and
+ // poke the provisioner for both TEE and SB.
+ keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT);
+ keyGen.notifyKeyGenerated(KeymasterDefs.KM_SECURITY_LEVEL_STRONGBOX);
+ } catch (RemoteException e) {
+ // Not really an error state. Does not apply at all if RKP is unsupported or
+ // disabled on a given device.
+ }
return new CredstoreWritableIdentityCredential(mContext, credentialName, docType, wc);
} catch (android.os.RemoteException e) {
throw new RuntimeException("Unexpected RemoteException ", e);
diff --git a/keystore/java/android/security/KeyStoreException.java b/keystore/java/android/security/KeyStoreException.java
index 54184dbf6e08..1a81dda8d56c 100644
--- a/keystore/java/android/security/KeyStoreException.java
+++ b/keystore/java/android/security/KeyStoreException.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.TestApi;
import android.security.keymaster.KeymasterDefs;
import android.system.keystore2.ResponseCode;
+import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -36,6 +37,8 @@ import java.util.Map;
* is likely to succeed.
*/
public class KeyStoreException extends Exception {
+ private static final String TAG = "KeyStoreException";
+
/**
* This error code is for mapping errors that the caller will not know about. If the caller is
* targeting an API level earlier than the one the error was introduced in, then the error will
@@ -114,6 +117,27 @@ public class KeyStoreException extends Exception {
* The caller should re-create the crypto object and try again.
*/
public static final int ERROR_KEY_OPERATION_EXPIRED = 15;
+ /**
+ * There are no keys available for attestation.
+ * This error is returned only on devices that rely solely on remotely-provisioned keys (see
+ * <a href=
+ * "https://android-developers.googleblog.com/2022/03/upgrading-android-attestation-remote.html"
+ * >Remote Key Provisioning</a>).
+ *
+ * <p>On such a device, if the caller requests key generation and includes an attestation
+ * challenge (indicating key attestation is required), the error will be returned in one of
+ * the following cases:
+ * <ul>
+ * <li>The pool of remotely-provisioned keys has been exhausted.</li>
+ * <li>The device is not registered with the key provisioning server.</li>
+ * </ul>
+ * </p>
+ *
+ * <p>This error is a transient one if the pool of remotely-provisioned keys has been
+ * exhausted. However, if the device is not registered with the server, or the key
+ * provisioning server refuses key issuance, this is a permanent error.</p>
+ */
+ public static final int ERROR_ATTESTATION_KEYS_UNAVAILABLE = 16;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@@ -132,11 +156,68 @@ public class KeyStoreException extends Exception {
ERROR_UNIMPLEMENTED,
ERROR_INCORRECT_USAGE,
ERROR_KEY_NOT_TEMPORALLY_VALID,
- ERROR_KEY_OPERATION_EXPIRED
+ ERROR_KEY_OPERATION_EXPIRED,
+ ERROR_ATTESTATION_KEYS_UNAVAILABLE
})
public @interface PublicErrorCode {
}
+ /**
+ * Never re-try the operation that led to this error, since it's a permanent error.
+ *
+ * This value is always returned when {@link #isTransientFailure()} is {@code false}.
+ */
+ public static final int RETRY_NEVER = 1;
+ /**
+ * Re-try the operation that led to this error with an exponential back-off delay.
+ * The first delay should be between 5 to 30 seconds, and each subsequent re-try should double
+ * the delay time.
+ *
+ * This value is returned when {@link #isTransientFailure()} is {@code true}.
+ */
+ public static final int RETRY_WITH_EXPONENTIAL_BACKOFF = 2;
+ /**
+ * Re-try the operation that led to this error when the device regains connectivity.
+ * Remote provisioning of keys requires reaching the remote server, and the device is
+ * currently unable to due that due to lack of network connectivity.
+ *
+ * This value is returned when {@link #isTransientFailure()} is {@code true}.
+ */
+ public static final int RETRY_WHEN_CONNECTIVITY_AVAILABLE = 3;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = {"RETRY_"}, value = {
+ RETRY_NEVER,
+ RETRY_WITH_EXPONENTIAL_BACKOFF,
+ RETRY_WHEN_CONNECTIVITY_AVAILABLE,
+ })
+ public @interface RetryPolicy {
+ }
+
+ // RKP-specific error information.
+ /**
+ * Remote provisioning of attestation keys has completed successfully.
+ * @hide */
+ public static final int RKP_SUCCESS = 0;
+ /**
+ * Remotely-provisioned keys are temporarily unavailable. This could be because of RPC
+ * error when talking to the remote provisioner or keys are being currently fetched and will
+ * be available soon.
+ * @hide */
+ public static final int RKP_TEMPORARILY_UNAVAILABLE = 1;
+ /**
+ * Permanent failure: The RKP server has declined issuance of keys to this device. Either
+ * because the device is not registered with the server or the server considers the device
+ * not to be trustworthy.
+ * @hide */
+ public static final int RKP_SERVER_REFUSED_ISSUANCE = 2;
+ /**
+ * The RKP server is unavailable due to lack of connectivity. The caller should re-try
+ * when the device has connectivity again.
+ * @hide */
+ public static final int RKP_FETCHING_PENDING_CONNECTIVITY = 3;
+
// Constants for encoding information about the error encountered:
// Whether the error relates to the system state/implementation as a whole, or a specific key.
private static final int IS_SYSTEM_ERROR = 1 << 1;
@@ -148,6 +229,21 @@ public class KeyStoreException extends Exception {
// The internal error code. NOT to be returned directly to callers or made part of the
// public API.
private final int mErrorCode;
+ // The Remote Key Provisioning status. Applicable if and only if {@link #mErrorCode} is equal
+ // to {@link ResponseCode.OUT_OF_KEYS}.
+ private final int mRkpStatus;
+
+ private static int initializeRkpStatusForRegularErrors(int errorCode) {
+ // Check if the system code mistakenly called a constructor of KeyStoreException with
+ // the OUT_OF_KEYS error code but without RKP status.
+ if (errorCode == ResponseCode.OUT_OF_KEYS) {
+ Log.e(TAG, "RKP error code without RKP status");
+ // Set RKP status to RKP_SERVER_REFUSED_ISSUANCE so that the caller never retries.
+ return RKP_SERVER_REFUSED_ISSUANCE;
+ } else {
+ return RKP_SUCCESS;
+ }
+ }
/**
* @hide
@@ -155,6 +251,7 @@ public class KeyStoreException extends Exception {
public KeyStoreException(int errorCode, @Nullable String message) {
super(message);
mErrorCode = errorCode;
+ mRkpStatus = initializeRkpStatusForRegularErrors(errorCode);
}
/**
@@ -165,6 +262,19 @@ public class KeyStoreException extends Exception {
super(message + " (internal Keystore code: " + errorCode + " message: "
+ keystoreErrorMessage + ")");
mErrorCode = errorCode;
+ mRkpStatus = initializeRkpStatusForRegularErrors(errorCode);
+ }
+
+ /**
+ * @hide
+ */
+ public KeyStoreException(int errorCode, @Nullable String message, int rkpStatus) {
+ super(message);
+ mErrorCode = errorCode;
+ mRkpStatus = rkpStatus;
+ if (mErrorCode != ResponseCode.OUT_OF_KEYS) {
+ Log.e(TAG, "Providing RKP status for error code " + errorCode + " has no effect.");
+ }
}
/**
@@ -198,6 +308,17 @@ public class KeyStoreException extends Exception {
*/
public boolean isTransientFailure() {
PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+ // Special-case handling for RKP failures:
+ if (mRkpStatus != RKP_SUCCESS && mErrorCode == ResponseCode.OUT_OF_KEYS) {
+ switch (mRkpStatus) {
+ case RKP_TEMPORARILY_UNAVAILABLE:
+ case RKP_FETCHING_PENDING_CONNECTIVITY:
+ return true;
+ case RKP_SERVER_REFUSED_ISSUANCE:
+ default:
+ return false;
+ }
+ }
return (failureInfo.indicators & IS_TRANSIENT_ERROR) != 0;
}
@@ -225,6 +346,34 @@ public class KeyStoreException extends Exception {
return (failureInfo.indicators & IS_SYSTEM_ERROR) != 0;
}
+ /**
+ * Returns the re-try policy for transient failures. Valid only if
+ * {@link #isTransientFailure()} returns {@code True}.
+ */
+ @RetryPolicy
+ public int getRetryPolicy() {
+ PublicErrorInformation failureInfo = getErrorInformation(mErrorCode);
+ // Special-case handling for RKP failures:
+ if (mRkpStatus != RKP_SUCCESS) {
+ switch (mRkpStatus) {
+ case RKP_TEMPORARILY_UNAVAILABLE:
+ return RETRY_WITH_EXPONENTIAL_BACKOFF;
+ case RKP_FETCHING_PENDING_CONNECTIVITY:
+ return RETRY_WHEN_CONNECTIVITY_AVAILABLE;
+ case RKP_SERVER_REFUSED_ISSUANCE:
+ return RETRY_NEVER;
+ default:
+ return (failureInfo.indicators & IS_TRANSIENT_ERROR) != 0
+ ? RETRY_WITH_EXPONENTIAL_BACKOFF : RETRY_NEVER;
+ }
+ }
+ if ((failureInfo.indicators & IS_TRANSIENT_ERROR) != 0) {
+ return RETRY_WITH_EXPONENTIAL_BACKOFF;
+ } else {
+ return RETRY_NEVER;
+ }
+ }
+
@Override
public String toString() {
String errorCodes = String.format(" (public error code: %d internal Keystore code: %d)",
@@ -469,5 +618,7 @@ public class KeyStoreException extends Exception {
new PublicErrorInformation(0, ERROR_KEY_CORRUPTED));
sErrorCodeToFailureInfo.put(ResponseCode.KEY_PERMANENTLY_INVALIDATED,
new PublicErrorInformation(0, ERROR_KEY_DOES_NOT_EXIST));
+ sErrorCodeToFailureInfo.put(ResponseCode.OUT_OF_KEYS,
+ new PublicErrorInformation(IS_SYSTEM_ERROR, ERROR_ATTESTATION_KEYS_UNAVAILABLE));
}
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
index e7961c94928c..5950b5bc7231 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -28,7 +28,6 @@ import android.hardware.security.keymint.Tag;
import android.os.Build;
import android.os.RemoteException;
import android.security.GenerateRkpKey;
-import android.security.GenerateRkpKeyException;
import android.security.KeyPairGeneratorSpec;
import android.security.KeyStore2;
import android.security.KeyStoreException;
@@ -618,18 +617,44 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
@Override
public KeyPair generateKeyPair() {
- try {
- return generateKeyPairHelper();
- } catch (GenerateRkpKeyException e) {
- try {
- return generateKeyPairHelper();
- } catch (GenerateRkpKeyException f) {
- throw new ProviderException("Failed to provision new attestation keys.");
+ GenerateKeyPairHelperResult result = new GenerateKeyPairHelperResult(0, null);
+ for (int i = 0; i < 2; i++) {
+ /**
+ * NOTE: There is no need to delay between re-tries because the call to
+ * GenerateRkpKey.notifyEmpty() will delay for a while before returning.
+ */
+ result = generateKeyPairHelper();
+ if (result.rkpStatus == KeyStoreException.RKP_SUCCESS) {
+ return result.keyPair;
}
}
+
+ // RKP failure
+ if (result.rkpStatus != KeyStoreException.RKP_SUCCESS) {
+ KeyStoreException ksException = new KeyStoreException(ResponseCode.OUT_OF_KEYS,
+ "Could not get RKP keys", result.rkpStatus);
+ throw new ProviderException("Failed to provision new attestation keys.", ksException);
+ }
+
+ return result.keyPair;
+ }
+
+ private static class GenerateKeyPairHelperResult {
+ // Zero indicates success, non-zero indicates failure. Values should be
+ // {@link android.security.KeyStoreException#RKP_TEMPORARILY_UNAVAILABLE},
+ // {@link android.security.KeyStoreException#RKP_SERVER_REFUSED_ISSUANCE},
+ // {@link android.security.KeyStoreException#RKP_FETCHING_PENDING_CONNECTIVITY}
+ public final int rkpStatus;
+ @Nullable
+ public final KeyPair keyPair;
+
+ private GenerateKeyPairHelperResult(int rkpStatus, KeyPair keyPair) {
+ this.rkpStatus = rkpStatus;
+ this.keyPair = keyPair;
+ }
}
- private KeyPair generateKeyPairHelper() throws GenerateRkpKeyException {
+ private GenerateKeyPairHelperResult generateKeyPairHelper() {
if (mKeyStore == null || mSpec == null) {
throw new IllegalStateException("Not initialized");
}
@@ -679,7 +704,8 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
Log.d(TAG, "Couldn't connect to the RemoteProvisioner backend.", e);
}
success = true;
- return new KeyPair(publicKey, publicKey.getPrivateKey());
+ KeyPair kp = new KeyPair(publicKey, publicKey.getPrivateKey());
+ return new GenerateKeyPairHelperResult(0, kp);
} catch (android.security.KeyStoreException e) {
switch (e.getErrorCode()) {
case KeymasterDefs.KM_ERROR_HARDWARE_TYPE_UNAVAILABLE:
@@ -688,11 +714,19 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
GenerateRkpKey keyGen = new GenerateRkpKey(ActivityThread
.currentApplication());
try {
+ //TODO: When detailed error information is available from the remote
+ //provisioner, propagate it up.
keyGen.notifyEmpty(securityLevel);
} catch (RemoteException f) {
- throw new ProviderException("Failed to talk to RemoteProvisioner", f);
+ KeyStoreException ksException = new KeyStoreException(
+ ResponseCode.OUT_OF_KEYS,
+ "Remote exception: " + f.getMessage(),
+ KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE);
+ throw new ProviderException("Failed to talk to RemoteProvisioner",
+ ksException);
}
- throw new GenerateRkpKeyException();
+ return new GenerateKeyPairHelperResult(
+ KeyStoreException.RKP_TEMPORARILY_UNAVAILABLE, null);
default:
ProviderException p = new ProviderException("Failed to generate key pair.", e);
if ((mSpec.getPurposes() & KeyProperties.PURPOSE_WRAP_KEY) != 0) {
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 59d03c738723..a2f9e884b37d 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -74,6 +74,10 @@
<!-- PIP stash offset size, which is the width of visible PIP region when stashed. -->
<dimen name="pip_stash_offset">32dp</dimen>
+ <!-- PIP shadow radius, originally as
+ WindowConfiguration#PINNED_WINDOWING_MODE_ELEVATION_IN_DIP -->
+ <dimen name="pip_shadow_radius">5dp</dimen>
+
<dimen name="dismiss_target_x_size">24dp</dimen>
<dimen name="floating_dismiss_bottom_margin">50dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java
index 7cf359729ee8..e71a59d26740 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimation.java
@@ -16,6 +16,7 @@
package com.android.wm.shell.back;
+import android.view.KeyEvent;
import android.view.MotionEvent;
import android.window.BackEvent;
@@ -29,8 +30,14 @@ public interface BackAnimation {
/**
* Called when a {@link MotionEvent} is generated by a back gesture.
+ *
+ * @param event the original {@link MotionEvent}
+ * @param action the original {@link KeyEvent#getAction()} when the event was dispatched to
+ * the process. This is forwarded separately because the input pipeline may mutate
+ * the {#event} action state later.
+ * @param swipeEdge the edge from which the swipe begins.
*/
- void onBackMotion(MotionEvent event, @BackEvent.SwipeEdge int swipeEdge);
+ void onBackMotion(MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge);
/**
* Sets whether the back gesture is past the trigger threshold or not.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index 08cb252cdf43..93ee3f5378e8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -138,8 +138,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
}
@Override
- public void onBackMotion(MotionEvent event, @BackEvent.SwipeEdge int swipeEdge) {
- mShellExecutor.execute(() -> onMotionEvent(event, swipeEdge));
+ public void onBackMotion(
+ MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge) {
+ mShellExecutor.execute(() -> onMotionEvent(event, action, swipeEdge));
}
@Override
@@ -209,13 +210,13 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
* Called when a new motion event needs to be transferred to this
* {@link BackAnimationController}
*/
- public void onMotionEvent(MotionEvent event, @BackEvent.SwipeEdge int swipeEdge) {
- int action = event.getActionMasked();
+ public void onMotionEvent(MotionEvent event, int action, @BackEvent.SwipeEdge int swipeEdge) {
if (action == MotionEvent.ACTION_DOWN) {
initAnimation(event);
} else if (action == MotionEvent.ACTION_MOVE) {
onMove(event, swipeEdge);
} else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ ProtoLog.d(WM_SHELL_BACK_PREVIEW, "Finishing gesture with event: %s", event);
onGestureFinished();
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl
index ef627647794e..062e3ba26356 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPipAnimationListener.aidl
@@ -26,12 +26,13 @@ oneway interface IPipAnimationListener {
void onPipAnimationStarted();
/**
- * Notifies the listener about PiP round corner radius changes.
+ * Notifies the listener about PiP resource dimensions changed.
* Listener can expect an immediate callback the first time they attach.
*
* @param cornerRadius the pixel value of the corner radius, zero means it's disabled.
+ * @param shadowRadius the pixel value of the shadow radius, zero means it's disabled.
*/
- void onPipCornerRadiusChanged(int cornerRadius);
+ void onPipResourceDimensionsChanged(int cornerRadius, int shadowRadius);
/**
* Notifies the listener that user leaves PiP by tapping on the expand button.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index 77fd228af286..30601d732593 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -489,7 +489,8 @@ public class PipAnimationController {
final float alpha = getStartValue() * (1 - fraction) + getEndValue() * fraction;
setCurrentValue(alpha);
getSurfaceTransactionHelper().alpha(tx, leash, alpha)
- .round(tx, leash, shouldApplyCornerRadius());
+ .round(tx, leash, shouldApplyCornerRadius())
+ .shadow(tx, leash);
tx.apply();
}
@@ -502,7 +503,8 @@ public class PipAnimationController {
getSurfaceTransactionHelper()
.resetScale(tx, leash, getDestinationBounds())
.crop(tx, leash, getDestinationBounds())
- .round(tx, leash, shouldApplyCornerRadius());
+ .round(tx, leash, shouldApplyCornerRadius())
+ .shadow(tx, leash);
tx.show(leash);
tx.apply();
}
@@ -589,7 +591,8 @@ public class PipAnimationController {
} else {
getSurfaceTransactionHelper().crop(tx, leash, base)
.scale(tx, leash, base, bounds, angle)
- .round(tx, leash, base, bounds);
+ .round(tx, leash, base, bounds)
+ .shadow(tx, leash);
}
} else {
final Rect insets = computeInsets(fraction);
@@ -598,8 +601,9 @@ public class PipAnimationController {
if (shouldApplyCornerRadius()) {
final Rect sourceBounds = new Rect(initialContainerRect);
sourceBounds.inset(insets);
- getSurfaceTransactionHelper().round(tx, leash,
- sourceBounds, bounds);
+ getSurfaceTransactionHelper()
+ .round(tx, leash, sourceBounds, bounds)
+ .shadow(tx, leash);
}
}
if (!handlePipTransaction(leash, tx, bounds)) {
@@ -650,7 +654,9 @@ public class PipAnimationController {
insets, degree, x, y, isOutPipDirection,
rotationDelta == ROTATION_270 /* clockwise */);
if (shouldApplyCornerRadius()) {
- getSurfaceTransactionHelper().round(tx, leash, sourceBounds, bounds);
+ getSurfaceTransactionHelper()
+ .round(tx, leash, sourceBounds, bounds)
+ .shadow(tx, leash);
}
tx.apply();
}
@@ -668,7 +674,8 @@ public class PipAnimationController {
void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
getSurfaceTransactionHelper()
.alpha(tx, leash, 1f)
- .round(tx, leash, shouldApplyCornerRadius());
+ .round(tx, leash, shouldApplyCornerRadius())
+ .shadow(tx, leash);
// TODO(b/178632364): this is a work around for the black background when
// entering PiP in buttion navigation mode.
if (isInPipDirection(direction)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
index d7322ce7beda..24ad2c18aaa4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
@@ -37,6 +37,7 @@ public class PipSurfaceTransactionHelper {
private final Rect mTmpDestinationRect = new Rect();
private int mCornerRadius;
+ private int mShadowRadius;
/**
* Called when display size or font size of settings changed
@@ -45,6 +46,7 @@ public class PipSurfaceTransactionHelper {
*/
public void onDensityOrFontScaleChanged(Context context) {
mCornerRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius);
+ mShadowRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_shadow_radius);
}
/**
@@ -200,14 +202,11 @@ public class PipSurfaceTransactionHelper {
}
/**
- * Re-parents the snapshot to the parent's surface control and shows it.
+ * Operates the shadow radius on a given transaction and leash
+ * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
*/
- public PipSurfaceTransactionHelper reparentAndShowSurfaceSnapshot(
- SurfaceControl.Transaction t, SurfaceControl parent, SurfaceControl snapshot) {
- t.reparent(snapshot, parent);
- t.setLayer(snapshot, Integer.MAX_VALUE);
- t.show(snapshot);
- t.apply();
+ public PipSurfaceTransactionHelper shadow(SurfaceControl.Transaction tx, SurfaceControl leash) {
+ tx.setShadowRadius(leash, mShadowRadius);
return this;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index ad5d85cc083a..623ef05ec7e2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -131,12 +131,13 @@ public class PipController implements PipTransitionController.PipTransitionCallb
void onPipAnimationStarted();
/**
- * Notifies the listener about PiP round corner radius changes.
+ * Notifies the listener about PiP resource dimensions changed.
* Listener can expect an immediate callback the first time they attach.
*
* @param cornerRadius the pixel value of the corner radius, zero means it's disabled.
+ * @param shadowRadius the pixel value of the shadow radius, zero means it's disabled.
*/
- void onPipCornerRadiusChanged(int cornerRadius);
+ void onPipResourceDimensionsChanged(int cornerRadius, int shadowRadius);
/**
* Notifies the listener that user leaves PiP by tapping on the expand button.
@@ -479,7 +480,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb
private void onDensityOrFontScaleChanged() {
mPipTaskOrganizer.onDensityOrFontScaleChanged(mContext);
- onPipCornerRadiusChanged();
+ onPipResourceDimensionsChanged();
}
private void onOverlayChanged() {
@@ -590,14 +591,14 @@ public class PipController implements PipTransitionController.PipTransitionCallb
private void setPinnedStackAnimationListener(PipAnimationListener callback) {
mPinnedStackAnimationRecentsCallback = callback;
- onPipCornerRadiusChanged();
+ onPipResourceDimensionsChanged();
}
- private void onPipCornerRadiusChanged() {
+ private void onPipResourceDimensionsChanged() {
if (mPinnedStackAnimationRecentsCallback != null) {
- final int cornerRadius =
- mContext.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius);
- mPinnedStackAnimationRecentsCallback.onPipCornerRadiusChanged(cornerRadius);
+ mPinnedStackAnimationRecentsCallback.onPipResourceDimensionsChanged(
+ mContext.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius),
+ mContext.getResources().getDimensionPixelSize(R.dimen.pip_shadow_radius));
}
}
@@ -916,8 +917,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
@Override
- public void onPipCornerRadiusChanged(int cornerRadius) {
- mListener.call(l -> l.onPipCornerRadiusChanged(cornerRadius));
+ public void onPipResourceDimensionsChanged(int cornerRadius, int shadowRadius) {
+ mListener.call(l -> l.onPipResourceDimensionsChanged(cornerRadius, shadowRadius));
}
@Override
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
index f6abc75037ed..b137e92881a5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
@@ -28,9 +28,6 @@ import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
import org.junit.runner.RunWith
import org.junit.Test
import org.junit.runners.Parameterized
@@ -52,11 +49,6 @@ open class DismissBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScree
private val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
private val displaySize = DisplayMetrics()
- @Before
- open fun before() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition {
setup {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenShellTransit.kt
deleted file mode 100644
index dd744b3c45ab..000000000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreenShellTransit.kt
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2022 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.wm.shell.flicker.bubble
-
-import androidx.test.filters.FlakyTest
-import androidx.test.filters.RequiresDevice
-
-import com.android.server.wm.flicker.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.annotation.Group4
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
-
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@Group4
-@FlakyTest(bugId = 217777115)
-class DismissBubbleScreenShellTransit(
- testSpec: FlickerTestParameter
-) : DismissBubbleScreen(testSpec) {
- @Before
- override fun before() {
- Assume.assumeTrue(isShellTransitionsEnabled)
- }
-}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
index 2ec743c10413..f288b0a24d9d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
@@ -24,9 +24,6 @@ import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
import org.junit.runner.RunWith
import org.junit.Test
import org.junit.runners.Parameterized
@@ -47,11 +44,6 @@ import org.junit.runners.Parameterized
@Group4
open class ExpandBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen(testSpec) {
- @Before
- open fun before() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition {
setup {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenShellTransit.kt
deleted file mode 100644
index d92ec7781005..000000000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreenShellTransit.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2022 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.wm.shell.flicker.bubble
-
-import androidx.test.filters.FlakyTest
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.annotation.Group4
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@Group4
-@FlakyTest(bugId = 217777115)
-class ExpandBubbleScreenShellTransit(
- testSpec: FlickerTestParameter
-) : ExpandBubbleScreen(testSpec) {
- @Before
- override fun before() {
- Assume.assumeTrue(isShellTransitionsEnabled)
- }
-} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
index c43230e77683..0bb4d398bff4 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
@@ -17,15 +17,11 @@
package com.android.wm.shell.flicker.bubble
import android.platform.test.annotations.Presubmit
-import androidx.test.filters.FlakyTest
import android.platform.test.annotations.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
@@ -45,11 +41,6 @@ import org.junit.runners.Parameterized
@Group4
open class LaunchBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen(testSpec) {
- @Before
- open fun before() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition {
transitions {
@@ -61,16 +52,6 @@ open class LaunchBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen
@Presubmit
@Test
open fun testAppIsAlwaysVisible() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- testSpec.assertLayers {
- this.isVisible(testApp.component)
- }
- }
-
- @FlakyTest(bugId = 218642026)
- @Test
- open fun testAppIsAlwaysVisible_ShellTransit() {
- Assume.assumeTrue(isShellTransitionsEnabled)
testSpec.assertLayers {
this.isVisible(testApp.component)
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenShellTransit.kt
deleted file mode 100644
index 9350868a99f4..000000000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreenShellTransit.kt
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2022 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.wm.shell.flicker.bubble
-
-import androidx.test.filters.FlakyTest
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.annotation.Group4
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@Group4
-@FlakyTest(bugId = 217777115)
-class LaunchBubbleScreenShellTransit(
- testSpec: FlickerTestParameter
-) : LaunchBubbleScreen(testSpec) {
- @Before
- override fun before() {
- Assume.assumeTrue(isShellTransitionsEnabled)
- }
-}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
index e2d08346efb6..a3ed79bf0409 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
@@ -74,7 +74,7 @@ class ExitPipViaExpandButtonClickTest(
// This will bring PipApp to fullscreen
pipApp.expandPipWindowToApp(wmHelper)
// Wait until the other app is no longer visible
- wmHelper.waitForSurfaceAppeared(testApp.component)
+ wmHelper.waitForWindowSurfaceDisappeared(testApp.component)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt
index 87e927fd50ea..8729bb6776f0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest.kt
@@ -24,10 +24,7 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group3
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.traces.region.RegionSubject
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -61,11 +58,6 @@ import org.junit.runners.Parameterized
open class MovePipDownShelfHeightChangeTest(
testSpec: FlickerTestParameter
) : MovePipShelfHeightTransition(testSpec) {
- @Before
- open fun before() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- }
-
/**
* Defines the transition used to run the test
*/
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest_ShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest_ShellTransit.kt
deleted file mode 100644
index 0ff260b94dc8..000000000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipDownShelfHeightChangeTest_ShellTransit.kt
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2021 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.wm.shell.flicker.pip
-
-import androidx.test.filters.FlakyTest
-import android.platform.test.annotations.RequiresDevice
-import com.android.server.wm.flicker.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.annotation.Group3
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test Pip movement with Launcher shelf height change (decrease).
- *
- * To run this test: `atest WMShellFlickerTests:MovePipDownShelfHeightChangeTest`
- *
- * Actions:
- * Launch [pipApp] in pip mode
- * Launch [testApp]
- * Press home
- * Check if pip window moves down (visually)
- *
- * Notes:
- * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
- * are inherited [PipTransition]
- * 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
- * including configuring navigation mode, initial orientation and ensuring no
- * apps are running before setup
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Group3
-@FlakyTest(bugId = 219693385)
-class MovePipDownShelfHeightChangeTest_ShellTransit(
- testSpec: FlickerTestParameter
-) : MovePipDownShelfHeightChangeTest(testSpec) {
- @Before
- override fun before() {
- Assume.assumeTrue(isShellTransitionsEnabled)
- }
-}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index c8ced1c9df12..6af01e24f58c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -64,7 +64,6 @@ import org.junit.runners.Parameterized
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group4
-@FlakyTest(bugId = 218604389)
open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
private val fixedApp = FixedAppHelper(instrumentation)
private val screenBoundsStart = WindowUtils.getDisplayBounds(testSpec.startRotation)
@@ -138,7 +137,7 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS
*/
@Presubmit
@Test
- fun pipLayerRotates_StartingBounds() {
+ open fun pipLayerRotates_StartingBounds() {
testSpec.assertLayersStart {
visibleRegion(pipApp.component).coversAtMost(screenBoundsStart)
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestShellTransit.kt
index a017f56af5bd..2252a949ba00 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTestShellTransit.kt
@@ -34,10 +34,12 @@ import org.junit.runners.Parameterized
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group4
-@FlakyTest(bugId = 217777115)
class PipRotationTestShellTransit(testSpec: FlickerTestParameter) : PipRotationTest(testSpec) {
@Before
override fun before() {
Assume.assumeTrue(isShellTransitionsEnabled)
}
+
+ @FlakyTest(bugId = 227214914)
+ override fun pipLayerRotates_StartingBounds() = super.pipLayerRotates_StartingBounds()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
index f7384e742a04..81403d08ff20 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTest.kt
@@ -28,13 +28,10 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
import com.android.wm.shell.flicker.pip.PipTransition.BroadcastActionTrigger.Companion.ORIENTATION_LANDSCAPE
import com.android.wm.shell.flicker.testapp.Components
import com.android.wm.shell.flicker.testapp.Components.FixedActivity.EXTRA_FIXED_ORIENTATION
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -57,11 +54,6 @@ open class SetRequestedOrientationWhilePinnedTest(
private val startingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_0)
private val endingBounds = WindowUtils.getDisplayBounds(Surface.ROTATION_90)
- @Before
- open fun before() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- }
-
override val transition: FlickerBuilder.() -> Unit
get() = {
setup {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTestShellTransit.kt
deleted file mode 100644
index 8d764a8d0e69..000000000000
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/SetRequestedOrientationWhilePinnedTestShellTransit.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2022 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.wm.shell.flicker.pip
-
-import androidx.test.filters.FlakyTest
-import androidx.test.filters.RequiresDevice
-import com.android.server.wm.flicker.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.annotation.Group4
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test exiting Pip with orientation changes.
- * To run this test: `atest WMShellFlickerTests:SetRequestedOrientationWhilePinnedTestShellTransit`
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Group4
-@FlakyTest(bugId = 217777115)
-class SetRequestedOrientationWhilePinnedTestShellTransit(
- testSpec: FlickerTestParameter
-) : SetRequestedOrientationWhilePinnedTest(testSpec) {
- @Before
- override fun before() {
- Assume.assumeTrue(isShellTransitionsEnabled)
- }
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
index 05230a9417bb..7c1fae3a849b 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/back/BackAnimationControllerTest.java
@@ -118,6 +118,7 @@ public class BackAnimationControllerTest {
BackNavigationInfo.TYPE_CROSS_ACTIVITY);
mController.onMotionEvent(
MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0),
+ MotionEvent.ACTION_DOWN,
BackEvent.EDGE_LEFT);
verify(mTransaction).setBuffer(screenshotSurface, hardwareBuffer);
verify(mTransaction).setVisibility(screenshotSurface, true);
@@ -133,9 +134,11 @@ public class BackAnimationControllerTest {
BackNavigationInfo.TYPE_CROSS_ACTIVITY);
mController.onMotionEvent(
MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0),
+ MotionEvent.ACTION_DOWN,
BackEvent.EDGE_LEFT);
mController.onMotionEvent(
MotionEvent.obtain(10, 0, MotionEvent.ACTION_MOVE, 100, 100, 0),
+ MotionEvent.ACTION_MOVE,
BackEvent.EDGE_LEFT);
verify(mTransaction).setPosition(animationTarget.leash, 100, 100);
verify(mTransaction, atLeastOnce()).apply();
@@ -151,12 +154,14 @@ public class BackAnimationControllerTest {
// Check that back start is dispatched.
mController.onMotionEvent(
MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0),
+ MotionEvent.ACTION_DOWN,
BackEvent.EDGE_LEFT);
verify(mIOnBackInvokedCallback).onBackStarted();
// Check that back progress is dispatched.
mController.onMotionEvent(
MotionEvent.obtain(10, 0, MotionEvent.ACTION_MOVE, 100, 100, 0),
+ MotionEvent.ACTION_MOVE,
BackEvent.EDGE_LEFT);
ArgumentCaptor<BackEvent> backEventCaptor = ArgumentCaptor.forClass(BackEvent.class);
verify(mIOnBackInvokedCallback).onBackProgressed(backEventCaptor.capture());
@@ -166,6 +171,7 @@ public class BackAnimationControllerTest {
mController.setTriggerBack(true); // Fake trigger back
mController.onMotionEvent(
MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0),
+ MotionEvent.ACTION_UP,
BackEvent.EDGE_LEFT);
verify(mIOnBackInvokedCallback).onBackInvoked();
}
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 0e4a1f945b85..99fd463b0660 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -74,7 +74,15 @@ bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, con
if (backBuffer.get() == nullptr) {
return false;
}
- LightingInfo::updateLighting(lightGeometry, lightInfo);
+
+ // update the coordinates of the global light position based on surface rotation
+ SkPoint lightCenter = mVkSurface->getCurrentPreTransform().mapXY(lightGeometry.center.x,
+ lightGeometry.center.y);
+ LightGeometry localGeometry = lightGeometry;
+ localGeometry.center.x = lightCenter.fX;
+ localGeometry.center.y = lightCenter.fY;
+
+ LightingInfo::updateLighting(localGeometry, lightInfo);
renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer,
mVkSurface->getCurrentPreTransform());
diff --git a/media/jni/soundpool/SoundPool.cpp b/media/jni/soundpool/SoundPool.cpp
index 00c4a9782f33..a2826cb58ccf 100644
--- a/media/jni/soundpool/SoundPool.cpp
+++ b/media/jni/soundpool/SoundPool.cpp
@@ -85,12 +85,13 @@ bool checkLoop(int32_t *loop)
} // namespace
SoundPool::SoundPool(
- int32_t maxStreams, const audio_attributes_t* attributes, const std::string& opPackageName)
+ int32_t maxStreams, const audio_attributes_t& attributes,
+ const std::string& opPackageName)
: mStreamManager(maxStreams, kStreamManagerThreads, attributes, opPackageName)
{
ALOGV("%s(maxStreams=%d, attr={ content_type=%d, usage=%d, flags=0x%x, tags=%s })",
__func__, maxStreams,
- attributes->content_type, attributes->usage, attributes->flags, attributes->tags);
+ attributes.content_type, attributes.usage, attributes.flags, attributes.tags);
}
SoundPool::~SoundPool()
diff --git a/media/jni/soundpool/SoundPool.h b/media/jni/soundpool/SoundPool.h
index ffb1c997393a..6bb971b07e43 100644
--- a/media/jni/soundpool/SoundPool.h
+++ b/media/jni/soundpool/SoundPool.h
@@ -31,7 +31,7 @@ namespace android {
*/
class SoundPool {
public:
- SoundPool(int32_t maxStreams, const audio_attributes_t* attributes,
+ SoundPool(int32_t maxStreams, const audio_attributes_t& attributes,
const std::string& opPackageName = {});
~SoundPool();
diff --git a/media/jni/soundpool/StreamManager.cpp b/media/jni/soundpool/StreamManager.cpp
index 7f987e31d1d8..487a696d8765 100644
--- a/media/jni/soundpool/StreamManager.cpp
+++ b/media/jni/soundpool/StreamManager.cpp
@@ -106,10 +106,10 @@ int32_t StreamMap::getNextIdForStream(Stream* stream) const {
#pragma clang diagnostic ignored "-Wthread-safety-analysis"
StreamManager::StreamManager(
- int32_t streams, size_t threads, const audio_attributes_t* attributes,
+ int32_t streams, size_t threads, const audio_attributes_t& attributes,
std::string opPackageName)
: StreamMap(streams)
- , mAttributes(*attributes)
+ , mAttributes(attributes)
, mOpPackageName(std::move(opPackageName))
, mLockStreamManagerStop(streams == 1 || kForceLockStreamManagerStop)
{
diff --git a/media/jni/soundpool/StreamManager.h b/media/jni/soundpool/StreamManager.h
index 85b468cd2cbc..ec65b0c49dc4 100644
--- a/media/jni/soundpool/StreamManager.h
+++ b/media/jni/soundpool/StreamManager.h
@@ -387,7 +387,7 @@ class StreamManager : public StreamMap {
public:
// Note: the SoundPool pointer is only used for stream initialization.
// It is not stored in StreamManager.
- StreamManager(int32_t streams, size_t threads, const audio_attributes_t* attributes,
+ StreamManager(int32_t streams, size_t threads, const audio_attributes_t& attributes,
std::string opPackageName);
~StreamManager();
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool.cpp
index 14b0c11c986a..5264772be7c3 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool.cpp
@@ -520,7 +520,7 @@ android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz,
(audio_flags_mask_t) env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
ScopedUtfChars opPackageNameStr(env, opPackageName);
auto soundPool = std::make_shared<SoundPool>(
- maxChannels, &audioAttributes, opPackageNameStr.c_str());
+ maxChannels, audioAttributes, opPackageNameStr.c_str());
soundPool->setCallback(android_media_callback, nullptr /* user */);
// register with SoundPoolManager.
diff --git a/media/jni/soundpool/tests/soundpool_stress.cpp b/media/jni/soundpool/tests/soundpool_stress.cpp
index 7d9b6a21b5c4..0116a99b2ba9 100644
--- a/media/jni/soundpool/tests/soundpool_stress.cpp
+++ b/media/jni/soundpool/tests/soundpool_stress.cpp
@@ -274,7 +274,7 @@ int main(int argc, char *argv[])
.content_type = AUDIO_CONTENT_TYPE_MUSIC,
.usage = AUDIO_USAGE_MEDIA,
};
- auto soundPool = std::make_unique<SoundPool>(maxStreams, &aa);
+ auto soundPool = std::make_unique<SoundPool>(maxStreams, aa);
gCallbackManager.setSoundPool(soundPool.get());
soundPool->setCallback(StaticCallbackManager, &gCallbackManager);
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index 2af7e00f9128..38d851eb76aa 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -41,6 +41,10 @@ import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
import java.util.zip.GZIPInputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -51,8 +55,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
private static final String TAG = "InstallationAsyncTask";
private static final int MIN_SHARED_MEMORY_SIZE = 8 << 10; // 8KiB
- private static final int MAX_SHARED_MEMORY_SIZE = 1024 << 10; // 1MiB
- private static final int DEFAULT_SHARED_MEMORY_SIZE = 64 << 10; // 64KiB
+ private static final int MAX_SHARED_MEMORY_SIZE = 8 << 20; // 8MiB
+ private static final int DEFAULT_SHARED_MEMORY_SIZE = 512 << 10; // 512KiB
private static final String SHARED_MEMORY_SIZE_PROP =
"dynamic_system.data_transfer.shared_memory.size";
@@ -488,7 +492,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
installWritablePartition("userdata", mUserdataSize);
}
- private void installImages() throws IOException, ImageValidationException {
+ private void installImages() throws ExecutionException, IOException, ImageValidationException {
if (mStream != null) {
if (mIsZip) {
installStreamingZipUpdate();
@@ -500,7 +504,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
}
}
- private void installStreamingGzUpdate() throws IOException, ImageValidationException {
+ private void installStreamingGzUpdate()
+ throws ExecutionException, IOException, ImageValidationException {
Log.d(TAG, "To install a streaming GZ update");
installImage("system", mSystemSize, new GZIPInputStream(mStream));
}
@@ -528,7 +533,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
return total;
}
- private void installStreamingZipUpdate() throws IOException, ImageValidationException {
+ private void installStreamingZipUpdate()
+ throws ExecutionException, IOException, ImageValidationException {
Log.d(TAG, "To install a streaming ZIP update");
ZipInputStream zis = new ZipInputStream(mStream);
@@ -548,7 +554,8 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
}
}
- private void installLocalZipUpdate() throws IOException, ImageValidationException {
+ private void installLocalZipUpdate()
+ throws ExecutionException, IOException, ImageValidationException {
Log.d(TAG, "To install a local ZIP update");
Enumeration<? extends ZipEntry> entries = mZipFile.entries();
@@ -569,7 +576,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
}
private void installImageFromAnEntry(ZipEntry entry, InputStream is)
- throws IOException, ImageValidationException {
+ throws ExecutionException, IOException, ImageValidationException {
String name = entry.getName();
Log.d(TAG, "ZipEntry: " + name);
@@ -581,7 +588,7 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
}
private void installImage(String partitionName, long uncompressedSize, InputStream is)
- throws IOException, ImageValidationException {
+ throws ExecutionException, IOException, ImageValidationException {
SparseInputStream sis = new SparseInputStream(new BufferedInputStream(is));
@@ -637,27 +644,51 @@ class InstallationAsyncTask extends AsyncTask<String, Long, Throwable> {
long prevInstalledSize = 0;
long installedSize = 0;
byte[] bytes = new byte[memoryFile.length()];
- int numBytesRead;
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Future<Boolean> submitPromise = null;
+
+ while (true) {
+ final int numBytesRead = sis.read(bytes, 0, bytes.length);
+
+ if (submitPromise != null) {
+ // Wait until the previous submit task is complete.
+ while (true) {
+ try {
+ if (!submitPromise.get()) {
+ throw new IOException("Failed submitFromAshmem() to DynamicSystem");
+ }
+ break;
+ } catch (InterruptedException e) {
+ // Ignore.
+ }
+ }
+
+ // Publish the progress of the previous submit task.
+ if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
+ publishProgress(installedSize);
+ prevInstalledSize = installedSize;
+ }
+ }
+
+ // Ensure the previous submit task (submitPromise) is complete before exiting the loop.
+ if (numBytesRead < 0) {
+ break;
+ }
- while ((numBytesRead = sis.read(bytes, 0, bytes.length)) != -1) {
if (isCancelled()) {
return;
}
memoryFile.writeBytes(bytes, 0, 0, numBytesRead);
+ submitPromise =
+ executor.submit(() -> mInstallationSession.submitFromAshmem(numBytesRead));
- if (!mInstallationSession.submitFromAshmem(numBytesRead)) {
- throw new IOException("Failed write() to DynamicSystem");
- }
-
+ // Even though we update the bytes counter here, the actual progress is updated only
+ // after the submit task (submitPromise) is complete.
installedSize += numBytesRead;
-
- if (installedSize > prevInstalledSize + MIN_PROGRESS_TO_PUBLISH) {
- publishProgress(installedSize);
- prevInstalledSize = installedSize;
- }
}
+ // Ensure a 100% mark is published.
if (prevInstalledSize != partitionSize) {
publishProgress(partitionSize);
}
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index a9f5f8582403..804b8f187405 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1434,6 +1434,8 @@
<string name="guest_remove_guest_dialog_title">Remove guest?</string>
<!-- Label for button in confirmation dialog when resetting guest user [CHAR LIMIT=35] -->
<string name="guest_reset_guest_confirm_button">Reset</string>
+ <!-- Label for button in confirmation dialog when removing guest session [CHAR LIMIT=35] -->
+ <string name="guest_remove_guest_confirm_button">Remove</string>
<!-- Status message indicating the device is in the process of resetting the guest user. [CHAR_LIMIT=NONE] -->
<string name="guest_resetting">Resetting guest\u2026</string>
<!-- An option in a photo selection dialog to take a new photo [CHAR LIMIT=50] -->
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 1fc2b8563dc1..a10ca9e75355 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -495,6 +495,9 @@
<!-- Permission needed for CTS test - DefaultDisplayModeTest -->
<uses-permission android:name="android.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE" />
+ <!-- Permissions needed for manual testing telephony time zone detector behavior -->
+ <uses-permission android:name="android.permission.SUGGEST_TELEPHONY_TIME_AND_ZONE" />
+
<!-- Permissions needed for CTS test - TimeManagerTest -->
<uses-permission android:name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" />
<uses-permission android:name="android.permission.SUGGEST_EXTERNAL_TIME" />
@@ -671,6 +674,9 @@
<!-- Permission required for CTS test - CtsTelephonyTestCases -->
<uses-permission android:name="android.permission.BIND_TELECOM_CONNECTION_SERVICE" />
+ <!-- Permission required for CTS test - CtsPersistentDataBlockManagerTestCases -->
+ <uses-permission android:name="android.permission.ACCESS_PDB_STATE" />
+
<!-- Permission required for CTS test - CtsAppEnumerationTestCases -->
<uses-permission android:name="android.permission.MAKE_UID_VISIBLE" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8df614d3c522..9767f04ac9d4 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -873,9 +873,6 @@
<!-- Message of the confirmation dialog when exiting guest session [CHAR LIMIT=NONE] -->
<string name="guest_exit_guest_dialog_message">All apps and data in this session will be deleted.</string>
- <!-- Label for button in confirmation dialog when exiting guest session [CHAR LIMIT=35] -->
- <string name="guest_exit_guest_dialog_remove">Remove</string>
-
<!-- Title of the notification when resuming an existing guest session [CHAR LIMIT=NONE] -->
<string name="guest_wipe_session_title">Welcome back, guest!</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
index 567e7aa3d78f..034d1ff1b049 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/pip/PipSurfaceTransactionHelper.java
@@ -30,14 +30,16 @@ import android.window.PictureInPictureSurfaceTransaction;
*/
public class PipSurfaceTransactionHelper {
private final int mCornerRadius;
+ private final int mShadowRadius;
private final Matrix mTmpTransform = new Matrix();
private final float[] mTmpFloat9 = new float[9];
private final RectF mTmpSourceRectF = new RectF();
private final RectF mTmpDestinationRectF = new RectF();
private final Rect mTmpDestinationRect = new Rect();
- public PipSurfaceTransactionHelper(int cornerRadius) {
+ public PipSurfaceTransactionHelper(int cornerRadius, int shadowRadius) {
mCornerRadius = cornerRadius;
+ mShadowRadius = shadowRadius;
}
public PictureInPictureSurfaceTransaction scale(
@@ -52,9 +54,10 @@ public class PipSurfaceTransactionHelper {
final float cornerRadius = getScaledCornerRadius(sourceBounds, destinationBounds);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setPosition(leash, positionX, positionY)
- .setCornerRadius(leash, cornerRadius);
+ .setCornerRadius(leash, cornerRadius)
+ .setShadowRadius(leash, mShadowRadius);
return newPipSurfaceTransaction(positionX, positionY,
- mTmpFloat9, 0 /* rotation */, cornerRadius, sourceBounds);
+ mTmpFloat9, 0 /* rotation */, cornerRadius, mShadowRadius, sourceBounds);
}
public PictureInPictureSurfaceTransaction scale(
@@ -69,9 +72,10 @@ public class PipSurfaceTransactionHelper {
final float cornerRadius = getScaledCornerRadius(sourceBounds, destinationBounds);
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setPosition(leash, positionX, positionY)
- .setCornerRadius(leash, cornerRadius);
+ .setCornerRadius(leash, cornerRadius)
+ .setShadowRadius(leash, mShadowRadius);
return newPipSurfaceTransaction(positionX, positionY,
- mTmpFloat9, degree, cornerRadius, sourceBounds);
+ mTmpFloat9, degree, cornerRadius, mShadowRadius, sourceBounds);
}
public PictureInPictureSurfaceTransaction scaleAndCrop(
@@ -92,9 +96,10 @@ public class PipSurfaceTransactionHelper {
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setWindowCrop(leash, mTmpDestinationRect)
.setPosition(leash, left, top)
- .setCornerRadius(leash, cornerRadius);
+ .setCornerRadius(leash, cornerRadius)
+ .setShadowRadius(leash, mShadowRadius);
return newPipSurfaceTransaction(left, top,
- mTmpFloat9, 0 /* rotation */, cornerRadius, mTmpDestinationRect);
+ mTmpFloat9, 0 /* rotation */, cornerRadius, mShadowRadius, mTmpDestinationRect);
}
public PictureInPictureSurfaceTransaction scaleAndRotate(
@@ -124,9 +129,10 @@ public class PipSurfaceTransactionHelper {
tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
.setWindowCrop(leash, mTmpDestinationRect)
.setPosition(leash, adjustedPositionX, adjustedPositionY)
- .setCornerRadius(leash, cornerRadius);
+ .setCornerRadius(leash, cornerRadius)
+ .setShadowRadius(leash, mShadowRadius);
return newPipSurfaceTransaction(adjustedPositionX, adjustedPositionY,
- mTmpFloat9, degree, cornerRadius, mTmpDestinationRect);
+ mTmpFloat9, degree, cornerRadius, mShadowRadius, mTmpDestinationRect);
}
/** @return the round corner radius scaled by given from and to bounds */
@@ -137,12 +143,13 @@ public class PipSurfaceTransactionHelper {
}
private static PictureInPictureSurfaceTransaction newPipSurfaceTransaction(
- float posX, float posY, float[] float9, float rotation, float cornerRadius,
- Rect windowCrop) {
+ float posX, float posY, float[] float9, float rotation,
+ float cornerRadius, float shadowRadius, Rect windowCrop) {
return new PictureInPictureSurfaceTransaction.Builder()
.setPosition(posX, posY)
.setTransform(float9, rotation)
.setCornerRadius(cornerRadius)
+ .setShadowRadius(shadowRadius)
.setWindowCrop(windowCrop)
.build();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index fcabbbca6e34..3b8a29bfe8c4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -3562,8 +3562,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
pw.println(" udfpsEnrolled=" + isUdfpsEnrolled());
pw.println(" shouldListenForUdfps=" + shouldListenForFingerprint(true));
pw.println(" bouncerVisible=" + mBouncer);
- pw.println(" mStatusBarState="
- + StatusBarState.toShortString(mStatusBarState));
+ pw.println(" mStatusBarState=" + StatusBarState.toString(mStatusBarState));
}
}
if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 6f0cd47a3f70..ea366eaf4568 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -394,7 +394,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
pw.println(" mUserUnlockedWithBiometric: " + mUserUnlockedWithBiometric);
pw.println(" mRunningFPS: " + mRunningFPS);
pw.println(" mCanDismissLockScreen: " + mCanDismissLockScreen);
- pw.println(" mStatusBarState: " + StatusBarState.toShortString(mStatusBarState));
+ pw.println(" mStatusBarState: " + StatusBarState.toString(mStatusBarState));
pw.println(" mQsExpanded: " + mQsExpanded);
pw.println(" mInterpolatedDarkAmount: " + mInterpolatedDarkAmount);
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
index 22c69373336f..011881354e35 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
@@ -369,10 +369,15 @@ class ScreenDecorHwcLayer(context: Context, displayDecorationSupport: DisplayDec
* Update the rounded corner size.
*/
fun updateRoundedCornerSize(top: Int, bottom: Int) {
+ if (roundedCornerTopSize == top && roundedCornerBottomSize == bottom) {
+ return
+ }
roundedCornerTopSize = top
roundedCornerBottomSize = bottom
updateRoundedCornerDrawableBounds()
- invalidate()
+
+ // Use requestLayout() to trigger transparent region recalculated
+ requestLayout()
}
private fun updateRoundedCornerDrawableBounds() {
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 2ec9174caee6..ede2945be29a 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -1045,13 +1045,22 @@ public class ScreenDecorations extends CoreStartable implements Tunable , Dumpab
mExecutor.execute(() -> {
if (mOverlays == null) return;
if (SIZE.equals(key)) {
+ boolean hasReloadRoundedCornerRes = false;
if (newValue != null) {
try {
mRoundedCornerResDelegate.updateTuningSizeFactor(
Integer.parseInt(newValue));
+ hasReloadRoundedCornerRes = true;
} catch (Exception e) {
}
}
+
+ // When onTuningChanged() is not called through updateRoundedCornerRadii(),
+ // we need to reload rounded corner res to prevent incorrect dimen
+ if (!hasReloadRoundedCornerRes) {
+ mRoundedCornerResDelegate.reloadAll(mDisplayUniqueId);
+ }
+
updateRoundedCornerSize(
mRoundedCornerResDelegate.getTopRoundedSize(),
mRoundedCornerResDelegate.getBottomRoundedSize());
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index b8334a02e5f2..2a945ded08ef 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -185,7 +185,7 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
super.dump(fd, pw, args);
pw.println("mShowingUdfpsBouncer=" + mShowingUdfpsBouncer);
pw.println("mFaceDetectRunning=" + mFaceDetectRunning);
- pw.println("mStatusBarState=" + StatusBarState.toShortString(mStatusBarState));
+ pw.println("mStatusBarState=" + StatusBarState.toString(mStatusBarState));
pw.println("mQsExpanded=" + mQsExpanded);
pw.println("mIsBouncerVisible=" + mIsBouncerVisible);
pw.println("mInputBouncerHiddenAmount=" + mInputBouncerHiddenAmount);
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
index be326da8d3bf..b325700954c2 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java
@@ -77,7 +77,7 @@ class FalsingCollectorImpl implements FalsingCollector {
new StatusBarStateController.StateListener() {
@Override
public void onStateChanged(int newState) {
- logDebug("StatusBarState=" + StatusBarState.toShortString(newState));
+ logDebug("StatusBarState=" + StatusBarState.toString(newState));
mState = newState;
updateSessionActive();
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
index b60e26628c55..6a9317f2b543 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardListener.java
@@ -17,11 +17,14 @@
package com.android.systemui.clipboardoverlay;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_ENABLED;
+import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED;
+import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED;
import android.content.ClipboardManager;
import android.content.Context;
import android.provider.DeviceConfig;
+import com.android.internal.logging.UiEventLogger;
import com.android.systemui.CoreStartable;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.util.DeviceConfigProxy;
@@ -38,15 +41,18 @@ public class ClipboardListener extends CoreStartable
private final DeviceConfigProxy mDeviceConfig;
private final ClipboardOverlayControllerFactory mOverlayFactory;
private final ClipboardManager mClipboardManager;
+ private final UiEventLogger mUiEventLogger;
private ClipboardOverlayController mClipboardOverlayController;
@Inject
public ClipboardListener(Context context, DeviceConfigProxy deviceConfigProxy,
- ClipboardOverlayControllerFactory overlayFactory, ClipboardManager clipboardManager) {
+ ClipboardOverlayControllerFactory overlayFactory, ClipboardManager clipboardManager,
+ UiEventLogger uiEventLogger) {
super(context);
mDeviceConfig = deviceConfigProxy;
mOverlayFactory = overlayFactory;
mClipboardManager = clipboardManager;
+ mUiEventLogger = uiEventLogger;
}
@Override
@@ -62,11 +68,15 @@ public class ClipboardListener extends CoreStartable
if (!mClipboardManager.hasPrimaryClip()) {
return;
}
+ String clipSource = mClipboardManager.getPrimaryClipSource();
if (mClipboardOverlayController == null) {
mClipboardOverlayController = mOverlayFactory.create(mContext);
+ mUiEventLogger.log(CLIPBOARD_OVERLAY_ENTERED, 0, clipSource);
+ } else {
+ mUiEventLogger.log(CLIPBOARD_OVERLAY_UPDATED, 0, clipSource);
}
mClipboardOverlayController.setClipData(
- mClipboardManager.getPrimaryClip(), mClipboardManager.getPrimaryClipSource());
+ mClipboardManager.getPrimaryClip(), clipSource);
mClipboardOverlayController.setOnSessionCompleteListener(() -> {
// Session is complete, free memory until it's needed again.
mClipboardOverlayController = null;
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
index be2397d37bed..9861392ba463 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayController.java
@@ -21,6 +21,12 @@ import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
+import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ACTION_TAPPED;
+import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_EDIT_TAPPED;
+import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_REMOTE_COPY_TAPPED;
+import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_SWIPE_DISMISSED;
+import static com.android.systemui.clipboardoverlay.ClipboardOverlayEvent.CLIPBOARD_OVERLAY_TIMED_OUT;
+
import static java.util.Objects.requireNonNull;
import android.animation.Animator;
@@ -71,6 +77,7 @@ import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.policy.PhoneWindow;
import com.android.systemui.R;
import com.android.systemui.screenshot.DraggableConstraintLayout;
@@ -97,6 +104,7 @@ public class ClipboardOverlayController {
private static final int SWIPE_PADDING_DP = 12; // extra padding around views to allow swipe
private final Context mContext;
+ private final UiEventLogger mUiEventLogger;
private final DisplayManager mDisplayManager;
private final DisplayMetrics mDisplayMetrics;
private final WindowManager mWindowManager;
@@ -129,11 +137,14 @@ public class ClipboardOverlayController {
private boolean mBlockAttach = false;
- public ClipboardOverlayController(Context context, TimeoutHandler timeoutHandler) {
+ public ClipboardOverlayController(
+ Context context, TimeoutHandler timeoutHandler, UiEventLogger uiEventLogger) {
mDisplayManager = requireNonNull(context.getSystemService(DisplayManager.class));
final Context displayContext = context.createDisplayContext(getDefaultDisplay());
mContext = displayContext.createWindowContext(TYPE_SCREENSHOT, null);
+ mUiEventLogger = uiEventLogger;
+
mAccessibilityManager = AccessibilityManager.getInstance(mContext);
mTextClassifier = requireNonNull(context.getSystemService(TextClassificationManager.class))
.getTextClassifier();
@@ -175,6 +186,7 @@ public class ClipboardOverlayController {
@Override
public void onSwipeDismissInitiated(Animator animator) {
+ mUiEventLogger.log(CLIPBOARD_OVERLAY_SWIPE_DISMISSED);
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
@@ -222,7 +234,10 @@ public class ClipboardOverlayController {
mView.post(this::animateIn);
});
- mTimeoutHandler.setOnTimeoutRunnable(this::animateOut);
+ mTimeoutHandler.setOnTimeoutRunnable(() -> {
+ mUiEventLogger.log(CLIPBOARD_OVERLAY_TIMED_OUT);
+ animateOut();
+ });
mCloseDialogsReceiver = new BroadcastReceiver() {
@Override
@@ -306,7 +321,10 @@ public class ClipboardOverlayController {
chip.setText(action.getTitle());
chip.setContentDescription(action.getTitle());
chip.setIcon(action.getIcon(), false);
- chip.setPendingIntent(action.getActionIntent(), this::animateOut);
+ chip.setPendingIntent(action.getActionIntent(), () -> {
+ mUiEventLogger.log(CLIPBOARD_OVERLAY_ACTION_TAPPED);
+ animateOut();
+ });
chip.setAlpha(1);
return chip;
}
@@ -350,6 +368,7 @@ public class ClipboardOverlayController {
}
private void editImage(Uri uri) {
+ mUiEventLogger.log(CLIPBOARD_OVERLAY_EDIT_TAPPED);
String editorPackage = mContext.getString(R.string.config_screenshotEditor);
Intent editIntent = new Intent(Intent.ACTION_EDIT);
if (!TextUtils.isEmpty(editorPackage)) {
@@ -363,6 +382,7 @@ public class ClipboardOverlayController {
}
private void editText() {
+ mUiEventLogger.log(CLIPBOARD_OVERLAY_EDIT_TAPPED);
Intent editIntent = new Intent(mContext, EditTextActivity.class);
editIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
mContext.startActivity(editIntent);
@@ -370,6 +390,7 @@ public class ClipboardOverlayController {
}
private void showNearby() {
+ mUiEventLogger.log(CLIPBOARD_OVERLAY_REMOTE_COPY_TAPPED);
mContext.startActivity(getRemoteCopyIntent());
animateOut();
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerFactory.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerFactory.java
index e1c11c4e8b4d..275d295613f9 100644
--- a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayControllerFactory.java
@@ -18,6 +18,7 @@ package com.android.systemui.clipboardoverlay;
import android.content.Context;
+import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.screenshot.TimeoutHandler;
@@ -28,14 +29,17 @@ import javax.inject.Inject;
*/
@SysUISingleton
public class ClipboardOverlayControllerFactory {
+ private final UiEventLogger mUiEventLogger;
@Inject
- public ClipboardOverlayControllerFactory() {}
+ public ClipboardOverlayControllerFactory(UiEventLogger uiEventLogger) {
+ mUiEventLogger = uiEventLogger;
+ }
/**
* One new ClipboardOverlayController, coming right up!
*/
public ClipboardOverlayController create(Context context) {
- return new ClipboardOverlayController(context, new TimeoutHandler(context));
+ return new ClipboardOverlayController(context, new TimeoutHandler(context), mUiEventLogger);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java
new file mode 100644
index 000000000000..5604a9128261
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEvent.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.clipboardoverlay;
+
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+
+public enum ClipboardOverlayEvent implements UiEventLogger.UiEventEnum {
+ @UiEvent(doc = "clipboard overlay entered")
+ CLIPBOARD_OVERLAY_ENTERED(949),
+ @UiEvent(doc = "clipboard overlay updated")
+ CLIPBOARD_OVERLAY_UPDATED(950),
+ @UiEvent(doc = "clipboard edit tapped")
+ CLIPBOARD_OVERLAY_EDIT_TAPPED(951),
+ @UiEvent(doc = "clipboard action tapped")
+ CLIPBOARD_OVERLAY_ACTION_TAPPED(952),
+ @UiEvent(doc = "clipboard remote copy tapped")
+ CLIPBOARD_OVERLAY_REMOTE_COPY_TAPPED(953),
+ @UiEvent(doc = "clipboard overlay timed out")
+ CLIPBOARD_OVERLAY_TIMED_OUT(954),
+ @UiEvent(doc = "clipboard overlay dismiss tapped")
+ CLIPBOARD_OVERLAY_DISMISS_TAPPED(955),
+ @UiEvent(doc = "clipboard overlay swipe dismissed")
+ CLIPBOARD_OVERLAY_SWIPE_DISMISSED(956);
+
+ private final int mId;
+
+ ClipboardOverlayEvent(int id) {
+ mId = id;
+ }
+
+ @Override
+ public int getId() {
+ return mId;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
index f6aeb2ac4ebc..041de05aa3d4 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DependencyProvider.java
@@ -36,6 +36,7 @@ import android.view.IWindowManager;
import android.view.LayoutInflater;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.util.NotificationMessagingUtil;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardUpdateMonitor;
@@ -296,7 +297,8 @@ public class DependencyProvider {
/***/
@Provides
@SysUISingleton
- public ClipboardOverlayControllerFactory provideClipboardOverlayControllerFactory() {
- return new ClipboardOverlayControllerFactory();
+ public ClipboardOverlayControllerFactory provideClipboardOverlayControllerFactory(
+ UiEventLogger uiEventLogger) {
+ return new ClipboardOverlayControllerFactory(uiEventLogger);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
index c817f89c7a9b..4c444175eca1 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerResDelegate.kt
@@ -56,17 +56,17 @@ class RoundedCornerResDelegate(
private set
init {
- reloadDrawables()
+ reloadRes()
reloadMeasures()
}
fun reloadAll(newDisplayUniqueId: String?) {
displayUniqueId = newDisplayUniqueId
- reloadDrawables()
+ reloadRes()
reloadMeasures()
}
- private fun reloadDrawables() {
+ private fun reloadRes() {
val configIdx = DisplayUtils.getDisplayUniqueIdConfigIndex(res, displayUniqueId)
isMultipleRadius = getIsMultipleRadius(configIdx)
@@ -85,34 +85,6 @@ class RoundedCornerResDelegate(
arrayResId = R.array.config_roundedCornerBottomDrawableArray,
backupDrawableId = R.drawable.rounded_corner_bottom
) ?: roundedDrawable
-
- // If config_roundedCornerMultipleRadius set as true, ScreenDecorations respect the
- // (width, height) size of drawable/rounded.xml instead of rounded_corner_radius
- if (isMultipleRadius) {
- roundedSize = Size(
- roundedDrawable?.intrinsicWidth ?: 0,
- roundedDrawable?.intrinsicHeight ?: 0)
- topRoundedDrawable?.let {
- topRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
- }
- bottomRoundedDrawable?.let {
- bottomRoundedSize = Size(it.intrinsicWidth, it.intrinsicHeight)
- }
- } else {
- val defaultRadius = RoundedCorners.getRoundedCornerRadius(res, displayUniqueId)
- val topRadius = RoundedCorners.getRoundedCornerTopRadius(res, displayUniqueId)
- val bottomRadius = RoundedCorners.getRoundedCornerBottomRadius(res, displayUniqueId)
- roundedSize = Size(defaultRadius, defaultRadius)
- topRoundedSize = Size(topRadius, topRadius)
- bottomRoundedSize = Size(bottomRadius, bottomRadius)
- }
-
- if (topRoundedSize.width == 0) {
- topRoundedSize = roundedSize
- }
- if (bottomRoundedSize.width == 0) {
- bottomRoundedSize = roundedSize
- }
}
private fun reloadMeasures(roundedSizeFactor: Int? = null) {
@@ -137,17 +109,18 @@ class RoundedCornerResDelegate(
bottomRoundedSize = Size(bottomRadius, bottomRadius)
}
- roundedSizeFactor ?.let {
- val length: Int = (it * density).toInt()
- roundedSize = Size(length, length)
- }
-
if (topRoundedSize.width == 0) {
topRoundedSize = roundedSize
}
if (bottomRoundedSize.width == 0) {
bottomRoundedSize = roundedSize
}
+
+ if (roundedSizeFactor != null && roundedSizeFactor > 0) {
+ val length: Int = (roundedSizeFactor * density).toInt()
+ topRoundedSize = Size(length, length)
+ bottomRoundedSize = Size(length, length)
+ }
}
fun updateTuningSizeFactor(factor: Int) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 88555edd1e8b..b96eee717260 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -102,7 +102,7 @@ public class KeyguardService extends Service {
"persist.wm.enable_remote_keyguard_animation";
private static final int sEnableRemoteKeyguardAnimation =
- SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 1);
+ SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 2);
/**
* @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 0486fee4239d..890ddf0d6cac 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -47,6 +47,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.UserInfo;
+import android.graphics.Matrix;
import android.hardware.biometrics.BiometricSourceType;
import android.media.AudioAttributes;
import android.media.AudioManager;
@@ -236,6 +237,14 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
*/
private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
+ private static final int UNOCCLUDE_ANIMATION_DURATION = 250;
+
+ /**
+ * How far down to animate the unoccluding activity, in terms of percent of the activity's
+ * height.
+ */
+ private static final float UNOCCLUDE_TRANSLATE_DISTANCE_PERCENT = 0.1f;
+
/**
* Boolean option for doKeyguardLocked/doKeyguardTimeout which, when set to true, forces the
* keyguard to show even if it is disabled for the current user.
@@ -883,53 +892,91 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
};
+ private IRemoteAnimationRunner mOccludeAnimationRunner =
+ new ActivityLaunchRemoteAnimationRunner(mOccludeAnimationController);
+
/**
- * Animation controller for activities that unocclude the keyguard. This will play the launch
- * animation in reverse.
+ * Animation controller for activities that unocclude the keyguard. This does not use the
+ * ActivityLaunchAnimator since we're just translating down, rather than emerging from a view
+ * or the power button.
*/
- private final ActivityLaunchAnimator.Controller mUnoccludeAnimationController =
- new ActivityLaunchAnimator.Controller() {
- @Override
- public void onLaunchAnimationEnd(boolean isExpandingFullyAbove) {
- setOccluded(false /* isOccluded */, false /* animate */);
- }
+ private final IRemoteAnimationRunner mUnoccludeAnimationRunner =
+ new IRemoteAnimationRunner.Stub() {
- @Override
- public void onLaunchAnimationCancelled() {
- setOccluded(false /* isOccluded */, false /* animate */);
- }
+ @Nullable private ValueAnimator mUnoccludeAnimator;
+ private final Matrix mUnoccludeMatrix = new Matrix();
- @NonNull
@Override
- public ViewGroup getLaunchContainer() {
- return ((ViewGroup) mKeyguardViewControllerLazy.get()
- .getViewRootImpl().getView());
+ public void onAnimationCancelled() {
+ if (mUnoccludeAnimator != null) {
+ mUnoccludeAnimator.cancel();
+ }
}
@Override
- public void setLaunchContainer(@NonNull ViewGroup launchContainer) {
- // No-op, launch container is always the shade.
- Log.wtf(TAG, "Someone tried to change the launch container for the "
- + "ActivityLaunchAnimator, which should never happen.");
- }
+ public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
+ RemoteAnimationTarget[] wallpapers,
+ RemoteAnimationTarget[] nonApps,
+ IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
+ final RemoteAnimationTarget primary = apps[0];
- @NonNull
- @Override
- public LaunchAnimator.State createAnimatorState() {
- final int width = getLaunchContainer().getWidth();
- final int height = getLaunchContainer().getHeight();
+ if (primary == null) {
+ finishedCallback.onAnimationFinished();
+ return;
+ }
- // TODO(b/207399883): Unocclude animation. This currently ends instantly.
- return new LaunchAnimator.State(
- 0, height, 0, width, mWindowCornerRadius, mWindowCornerRadius);
+ final SyncRtSurfaceTransactionApplier applier =
+ new SyncRtSurfaceTransactionApplier(
+ mKeyguardViewControllerLazy.get().getViewRootImpl().getView());
+
+
+ mContext.getMainExecutor().execute(() -> {
+ if (mUnoccludeAnimator != null) {
+ mUnoccludeAnimator.cancel();
+ }
+
+ mUnoccludeAnimator = ValueAnimator.ofFloat(1f, 0f);
+ mUnoccludeAnimator.setDuration(UNOCCLUDE_ANIMATION_DURATION);
+ mUnoccludeAnimator.setInterpolator(Interpolators.TOUCH_RESPONSE);
+ mUnoccludeAnimator.addUpdateListener(
+ animation -> {
+ final float animatedValue =
+ (float) animation.getAnimatedValue();
+
+ final float surfaceHeight = primary.screenSpaceBounds.height();
+
+ mUnoccludeMatrix.setTranslate(
+ 0f,
+ (1f - animatedValue)
+ * surfaceHeight
+ * UNOCCLUDE_TRANSLATE_DISTANCE_PERCENT);
+
+ SyncRtSurfaceTransactionApplier.SurfaceParams params =
+ new SyncRtSurfaceTransactionApplier.SurfaceParams
+ .Builder(primary.leash)
+ .withMatrix(mUnoccludeMatrix)
+ .withCornerRadius(mWindowCornerRadius)
+ .withAlpha(animatedValue)
+ .build();
+ applier.scheduleApply(params);
+ });
+ mUnoccludeAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ try {
+ finishedCallback.onAnimationFinished();
+ mUnoccludeAnimator = null;
+ } catch (RemoteException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ mUnoccludeAnimator.start();
+ });
}
};
- private IRemoteAnimationRunner mOccludeAnimationRunner =
- new ActivityLaunchRemoteAnimationRunner(mOccludeAnimationController);
- private IRemoteAnimationRunner mUnoccludeAnimationRunner =
- new ActivityLaunchRemoteAnimationRunner(mUnoccludeAnimationController);
-
private DeviceConfigProxy mDeviceConfig;
private DozeParameters mDozeParameters;
diff --git a/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt b/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt
index f1058e28863a..fbd17d7a212e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt
@@ -13,6 +13,7 @@ import android.graphics.PixelFormat
import android.graphics.drawable.Drawable
import android.os.SystemClock
import androidx.annotation.VisibleForTesting
+import com.android.internal.graphics.ColorUtils
import com.android.systemui.animation.Interpolators
import kotlin.math.abs
import kotlin.math.cos
@@ -157,8 +158,7 @@ class SquigglyProgress : Drawable() {
}
override fun setAlpha(alpha: Int) {
- wavePaint.alpha = alpha
- linePaint.alpha = (DISABLED_ALPHA * (alpha / 255f)).toInt()
+ updateColors(wavePaint.color, alpha)
}
override fun getAlpha(): Int {
@@ -166,8 +166,7 @@ class SquigglyProgress : Drawable() {
}
override fun setTint(tintColor: Int) {
- wavePaint.color = tintColor
- linePaint.color = tintColor
+ updateColors(tintColor, alpha)
}
override fun onLevelChange(level: Int): Boolean {
@@ -178,7 +177,12 @@ class SquigglyProgress : Drawable() {
if (tint == null) {
return
}
- wavePaint.color = tint.defaultColor
- linePaint.color = tint.defaultColor
+ updateColors(tint.defaultColor, alpha)
+ }
+
+ private fun updateColors(tintColor: Int, alpha: Int) {
+ wavePaint.color = ColorUtils.setAlphaComponent(tintColor, alpha)
+ linePaint.color = ColorUtils.setAlphaComponent(tintColor,
+ (DISABLED_ALPHA * (alpha / 255f)).toInt())
}
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
index a1258df7a12c..03652412c129 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
@@ -480,7 +480,9 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
public void onMotionEvent(MotionEvent event) {
if (mBackAnimation != null) {
mBackAnimation.onBackMotion(
- event, mIsLeftPanel ? BackEvent.EDGE_LEFT : BackEvent.EDGE_RIGHT);
+ event,
+ event.getActionMasked(),
+ mIsLeftPanel ? BackEvent.EDGE_LEFT : BackEvent.EDGE_RIGHT);
}
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 8d0494afbb89..7f49bcd9d926 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -26,6 +26,7 @@ import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Trace;
+import android.util.IndentingPrintWriter;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
@@ -38,6 +39,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.keyguard.BouncerPanelExpansionCalculator;
+import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.ShadeInterpolation;
@@ -58,13 +60,16 @@ import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
import com.android.systemui.util.LifecycleFragment;
import com.android.systemui.util.Utils;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Named;
public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Callbacks,
- StatusBarStateController.StateListener {
+ StatusBarStateController.StateListener, Dumpable {
private static final String TAG = "QS";
private static final boolean DEBUG = false;
private static final String EXTRA_EXPANDED = "expanded";
@@ -135,7 +140,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
*/
private boolean mAnimateNextQsUpdate;
- private DumpManager mDumpManager;
+ private final DumpManager mDumpManager;
/**
* Progress of pull down from the center of the lock screen.
@@ -256,15 +261,26 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
}
@Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mDumpManager.registerDumpable(getClass().getName(), this);
+ }
+
+ @Override
public void onDestroy() {
super.onDestroy();
mStatusBarStateController.removeCallback(this);
if (mListening) {
setListening(false);
}
- mQSCustomizerController.setQs(null);
+ if (mQSCustomizerController != null) {
+ mQSCustomizerController.setQs(null);
+ }
mScrollListener = null;
- mDumpManager.unregisterDumpable(mContainer.getClass().getName());
+ if (mContainer != null) {
+ mDumpManager.unregisterDumpable(mContainer.getClass().getName());
+ }
+ mDumpManager.unregisterDumpable(getClass().getName());
}
@Override
@@ -272,7 +288,9 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
super.onSaveInstanceState(outState);
outState.putBoolean(EXTRA_EXPANDED, mQsExpanded);
outState.putBoolean(EXTRA_LISTENING, mListening);
- mQSCustomizerController.saveInstanceState(outState);
+ if (mQSCustomizerController != null) {
+ mQSCustomizerController.saveInstanceState(outState);
+ }
if (mQsExpanded) {
mQSPanelController.getTileLayout().saveInstanceState(outState);
}
@@ -594,7 +612,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
} else if (progress > 0 && view.getVisibility() != View.VISIBLE) {
view.setVisibility((View.VISIBLE));
}
- float alpha = (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
+ float alpha = mQSPanelController.bouncerInTransit()
? BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(progress)
: ShadeInterpolation.getContentAlpha(progress);
view.setAlpha(alpha);
@@ -787,4 +805,62 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
setKeyguardShowing(newState == StatusBarState.KEYGUARD);
updateShowCollapsedOnKeyguard();
}
+
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ IndentingPrintWriter indentingPw = new IndentingPrintWriter(pw, /* singleIndent= */ " ");
+ indentingPw.println("QSFragment:");
+ indentingPw.increaseIndent();
+ indentingPw.println("mQsBounds: " + mQsBounds);
+ indentingPw.println("mQsExpanded: " + mQsExpanded);
+ indentingPw.println("mHeaderAnimating: " + mHeaderAnimating);
+ indentingPw.println("mStackScrollerOverscrolling: " + mStackScrollerOverscrolling);
+ indentingPw.println("mListening: " + mListening);
+ indentingPw.println("mLayoutDirection: " + mLayoutDirection);
+ indentingPw.println("mLastQSExpansion: " + mLastQSExpansion);
+ indentingPw.println("mLastPanelFraction: " + mLastPanelFraction);
+ indentingPw.println("mSquishinessFraction: " + mSquishinessFraction);
+ indentingPw.println("mQsDisabled: " + mQsDisabled);
+ indentingPw.println("mTemp: " + Arrays.toString(mTemp));
+ indentingPw.println("mShowCollapsedOnKeyguard: " + mShowCollapsedOnKeyguard);
+ indentingPw.println("mLastKeyguardAndExpanded: " + mLastKeyguardAndExpanded);
+ indentingPw.println("mState: " + StatusBarState.toString(mState));
+ indentingPw.println("mTmpLocation: " + Arrays.toString(mTmpLocation));
+ indentingPw.println("mLastViewHeight: " + mLastViewHeight);
+ indentingPw.println("mLastHeaderTranslation: " + mLastHeaderTranslation);
+ indentingPw.println("mInSplitShade: " + mInSplitShade);
+ indentingPw.println("mTransitioningToFullShade: " + mTransitioningToFullShade);
+ indentingPw.println("mFullShadeProgress: " + mFullShadeProgress);
+ indentingPw.println("mOverScrolling: " + mOverScrolling);
+ indentingPw.println("isCustomizing: " + mQSCustomizerController.isCustomizing());
+ View view = getView();
+ if (view != null) {
+ indentingPw.println("top: " + view.getTop());
+ indentingPw.println("y: " + view.getY());
+ indentingPw.println("translationY: " + view.getTranslationY());
+ indentingPw.println("alpha: " + view.getAlpha());
+ indentingPw.println("height: " + view.getHeight());
+ indentingPw.println("measuredHeight: " + view.getMeasuredHeight());
+ indentingPw.println("clipBounds: " + view.getClipBounds());
+ } else {
+ indentingPw.println("getView(): null");
+ }
+ QuickStatusBarHeader header = mHeader;
+ if (header != null) {
+ indentingPw.println("headerHeight: " + header.getHeight());
+ indentingPw.println("Header visibility: " + visibilityToString(header.getVisibility()));
+ } else {
+ indentingPw.println("mHeader: null");
+ }
+ }
+
+ private static String visibilityToString(int visibility) {
+ if (visibility == View.VISIBLE) {
+ return "VISIBLE";
+ }
+ if (visibility == View.INVISIBLE) {
+ return "INVISIBLE";
+ }
+ return "GONE";
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index dd2929c9a67a..10d792098608 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -43,6 +43,7 @@ import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.brightness.BrightnessController;
import com.android.systemui.settings.brightness.BrightnessMirrorHandler;
import com.android.systemui.settings.brightness.BrightnessSliderController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
import com.android.systemui.tuner.TunerService;
@@ -65,6 +66,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
private final BrightnessSliderController mBrightnessSliderController;
private final BrightnessMirrorHandler mBrightnessMirrorHandler;
private final FeatureFlags mFeatureFlags;
+ private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private boolean mGridContentVisible = true;
@@ -101,7 +103,8 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
BrightnessSliderController.Factory brightnessSliderFactory,
- FalsingManager falsingManager, FeatureFlags featureFlags) {
+ FalsingManager falsingManager, FeatureFlags featureFlags,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
metricsLogger, uiEventLogger, qsLogger, dumpManager);
mQSFgsManagerFooter = qsFgsManagerFooter;
@@ -117,6 +120,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mBrightnessController = brightnessControllerFactory.create(mBrightnessSliderController);
mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
mFeatureFlags = featureFlags;
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
view.setUseNewFooter(featureFlags.isEnabled(Flags.NEW_FOOTER));
}
@@ -281,5 +285,14 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
void setPageMargin(int pageMargin) {
mView.setPageMargin(pageMargin);
}
+
+ /**
+ * Determines if bouncer expansion is between 0 and 1 non-inclusive.
+ *
+ * @return if bouncer is in transit
+ */
+ public boolean bouncerInTransit() {
+ return mStatusBarKeyguardViewManager.bouncerIsInTransit();
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
index 5c1d332df7a7..86ef85824eb0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
@@ -73,7 +73,7 @@ class QSLogger @Inject constructor(
log(DEBUG, {
str1 = tileSpec
int1 = statusBarState
- str2 = StatusBarState.toShortString(statusBarState)
+ str2 = StatusBarState.toString(statusBarState)
str3 = toStateString(state)
}, {
"[$str1] Tile clicked. StatusBarState=$str2. TileState=$str3"
@@ -84,7 +84,7 @@ class QSLogger @Inject constructor(
log(DEBUG, {
str1 = tileSpec
int1 = statusBarState
- str2 = StatusBarState.toShortString(statusBarState)
+ str2 = StatusBarState.toString(statusBarState)
str3 = toStateString(state)
}, {
"[$str1] Tile long clicked. StatusBarState=$str2. TileState=$str3"
@@ -95,7 +95,7 @@ class QSLogger @Inject constructor(
log(DEBUG, {
str1 = tileSpec
int1 = statusBarState
- str2 = StatusBarState.toShortString(statusBarState)
+ str2 = StatusBarState.toString(statusBarState)
str3 = toStateString(state)
}, {
"[$str1] Tile long clicked. StatusBarState=$str2. TileState=$str3"
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java
index 16bc951e0323..718bc5caf414 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarState.java
@@ -37,16 +37,19 @@ public class StatusBarState {
*/
public static final int SHADE_LOCKED = 2;
- public static String toShortString(int x) {
- switch (x) {
+ /**
+ * Returns the textual representation of the status bar state.
+ */
+ public static String toString(int state) {
+ switch (state) {
case SHADE:
- return "SHD";
+ return "SHADE";
case SHADE_LOCKED:
- return "SHD_LCK";
+ return "SHADE_LOCKED";
case KEYGUARD:
- return "KGRD";
+ return "KEYGUARD";
default:
- return "bad_value_" + x;
+ return "UNKNOWN: " + state;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 2763bd711338..19f59f76f8a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -508,7 +508,7 @@ public class StatusBarStateControllerImpl implements
* Returns String readable state of status bar from {@link StatusBarState}
*/
public static String describe(int state) {
- return StatusBarState.toShortString(state);
+ return StatusBarState.toString(state);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 32d37d18f407..c0553b5c3c2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -347,7 +347,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
setDimAmount((Float) animation.getAnimatedValue());
}
};
- protected ViewGroup mQsContainer;
+ protected ViewGroup mQsHeader;
+ // Rect of QsHeader. Kept as a field just to avoid creating a new one each time.
+ private Rect mQsHeaderBound = new Rect();
private boolean mContinuousShadowUpdate;
private boolean mContinuousBackgroundUpdate;
private ViewTreeObserver.OnPreDrawListener mShadowUpdater
@@ -1598,8 +1600,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
@ShadeViewRefactor(RefactorComponent.ADAPTER)
- public void setQsContainer(ViewGroup qsContainer) {
- mQsContainer = qsContainer;
+ public void setQsHeader(ViewGroup qsHeader) {
+ mQsHeader = qsHeader;
}
@ShadeViewRefactor(RefactorComponent.ADAPTER)
@@ -3458,7 +3460,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
if (!isScrollingEnabled()) {
return false;
}
- if (isInsideQsContainer(ev) && !mIsBeingDragged) {
+ if (isInsideQsHeader(ev) && !mIsBeingDragged) {
return false;
}
mForcedScroll = null;
@@ -3611,8 +3613,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
@ShadeViewRefactor(RefactorComponent.INPUT)
- protected boolean isInsideQsContainer(MotionEvent ev) {
- return ev.getY() < mQsContainer.getBottom();
+ protected boolean isInsideQsHeader(MotionEvent ev) {
+ mQsHeader.getBoundsOnScreen(mQsHeaderBound);
+ return mQsHeaderBound.contains((int) ev.getX(), (int) ev.getY());
}
@ShadeViewRefactor(RefactorComponent.INPUT)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 5bc50ae11fb7..3e630cdf8f97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -1234,8 +1234,9 @@ public class NotificationStackScrollLayoutController {
mView.setExpandedHeight(expandedHeight);
}
- public void setQsContainer(ViewGroup view) {
- mView.setQsContainer(view);
+ /** Sets the QS header. Used to check if a touch is within its bounds. */
+ public void setQsHeader(ViewGroup view) {
+ mView.setQsHeader(view);
}
public void setAnimationsEnabled(boolean enabled) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 2d16b52839eb..11628cb75e87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -3592,7 +3592,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
});
mLockscreenShadeTransitionController.setQS(mQs);
- mNotificationStackScrollLayoutController.setQsContainer((ViewGroup) mQs.getView());
+ mNotificationStackScrollLayoutController.setQsHeader((ViewGroup) mQs.getHeader());
mQs.setScrollListener(mScrollListener);
updateQsExpansion();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index be50a17b8536..71f199f330a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -797,10 +797,9 @@ public abstract class PanelViewController {
}
mExpandedFraction = Math.min(1f,
maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight);
- mAmbientState.setExpansionFraction(mKeyguardStateController.isUnlocked()
- ? mExpandedFraction
- : BouncerPanelExpansionCalculator
- .getBackScrimScaledExpansion(mExpandedFraction));
+ mAmbientState.setExpansionFraction(mStatusBarKeyguardViewManager.bouncerIsInTransit()
+ ? BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(mExpandedFraction)
+ : mExpandedFraction);
onHeightUpdated(mExpandedHeight);
updatePanelExpansionAndVisibility();
});
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 8272ed926255..a98ec58dc94c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -204,6 +204,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
private final Executor mMainExecutor;
private final ScreenOffAnimationController mScreenOffAnimationController;
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+ private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private GradientColors mColors;
private boolean mNeedsDrawableColorUpdate;
@@ -266,7 +267,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
ConfigurationController configurationController, @Main Executor mainExecutor,
ScreenOffAnimationController screenOffAnimationController,
PanelExpansionStateManager panelExpansionStateManager,
- KeyguardUnlockAnimationController keyguardUnlockAnimationController) {
+ KeyguardUnlockAnimationController keyguardUnlockAnimationController,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
mScrimStateListener = lightBarController::setScrimState;
mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
@@ -292,6 +294,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
keyguardStateController.getKeyguardFadingAwayDuration());
}
});
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
configurationController.addCallback(new ConfigurationController.ConfigurationListener() {
@Override
public void onThemeChanged() {
@@ -1021,6 +1024,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
if (aodWallpaperTimeout || occludedKeyguard) {
mBehindAlpha = 1;
}
+ // Prevent notification scrim flicker when transitioning away from keyguard.
+ if (mKeyguardStateController.isKeyguardGoingAway()) {
+ mNotificationsAlpha = 0;
+ }
setScrimAlpha(mScrimInFront, mInFrontAlpha);
setScrimAlpha(mScrimBehind, mBehindAlpha);
setScrimAlpha(mNotificationsScrim, mNotificationsAlpha);
@@ -1057,7 +1064,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
}
private float getInterpolatedFraction() {
- if (mState == ScrimState.KEYGUARD || mState == ScrimState.SHADE_LOCKED) {
+ if (mStatusBarKeyguardViewManager.bouncerIsInTransit()) {
return BouncerPanelExpansionCalculator
.getBackScrimScaledExpansion(mPanelExpansionFraction);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 23401618e1f3..a1cbba47e822 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -1368,6 +1368,15 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
/**
+ * Returns if bouncer expansion is between 0 and 1 non-inclusive.
+ */
+ public boolean bouncerIsInTransit() {
+ if (mBouncer == null) return false;
+
+ return mBouncer.inTransit();
+ }
+
+ /**
* Delegate used to send show/reset events to an alternate authentication method instead of the
* regular pin/pattern/password bouncer.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 8396639fe0f5..2c05a4ea8238 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -1155,7 +1155,8 @@ public class UserSwitcherController implements Dumpable {
setButton(DialogInterface.BUTTON_POSITIVE,
context.getString(mGuestUserAutoCreated
? com.android.settingslib.R.string.guest_reset_guest_confirm_button
- : R.string.guest_exit_guest_dialog_remove), this);
+ : com.android.settingslib.R.string.guest_remove_guest_confirm_button),
+ this);
SystemUIDialog.setWindowOnTop(this, mKeyguardStateController.isShowing());
setCanceledOnTouchOutside(false);
mGuestId = guestId;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 85a6eebf6bd7..e4c83a543d89 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -49,7 +49,6 @@ import android.os.VibrationEffect;
import android.provider.Settings;
import android.service.notification.Condition;
import android.service.notification.ZenModeConfig;
-import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
@@ -418,41 +417,8 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
}
private void onGetCaptionsComponentStateW(boolean fromTooltip) {
- if (mCaptioningManager.isSystemAudioCaptioningUiEnabled()) {
- mCallbacks.onCaptionComponentStateChanged(true, fromTooltip);
- return;
- }
-
- // TODO(b/220968335): Remove this check once system captions component migrates
- // to new CaptioningManager APIs.
- try {
- String componentNameString = mContext.getString(
- com.android.internal.R.string.config_defaultSystemCaptionsService);
- if (TextUtils.isEmpty(componentNameString)) {
- // component doesn't exist
- mCallbacks.onCaptionComponentStateChanged(false, fromTooltip);
- return;
- }
-
- if (D.BUG) {
- Log.i(TAG, String.format(
- "isCaptionsServiceEnabled componentNameString=%s", componentNameString));
- }
-
- ComponentName componentName = ComponentName.unflattenFromString(componentNameString);
- if (componentName == null) {
- mCallbacks.onCaptionComponentStateChanged(false, fromTooltip);
- return;
- }
-
- mCallbacks.onCaptionComponentStateChanged(
- mPackageManager.getComponentEnabledSetting(componentName)
- == PackageManager.COMPONENT_ENABLED_STATE_ENABLED, fromTooltip);
- } catch (Exception ex) {
- Log.e(TAG,
- "isCaptionsServiceEnabled failed to check for captions component", ex);
- mCallbacks.onCaptionComponentStateChanged(false, fromTooltip);
- }
+ mCallbacks.onCaptionComponentStateChanged(
+ mCaptioningManager.isSystemAudioCaptioningUiEnabled(), fromTooltip);
}
private void onAccessibilityModeChanged(Boolean showA11yStream) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
index e15b6cc62644..de04d3e9d059 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardListenerTest.java
@@ -32,6 +32,7 @@ import android.provider.DeviceConfig;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.logging.UiEventLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.DeviceConfigProxyFake;
@@ -53,6 +54,8 @@ public class ClipboardListenerTest extends SysuiTestCase {
private ClipboardOverlayControllerFactory mClipboardOverlayControllerFactory;
@Mock
private ClipboardOverlayController mOverlayController;
+ @Mock
+ private UiEventLogger mUiEventLogger;
private DeviceConfigProxyFake mDeviceConfigProxy;
private ClipData mSampleClipData;
@@ -87,9 +90,10 @@ public class ClipboardListenerTest extends SysuiTestCase {
mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
"false", false);
ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
- mClipboardOverlayControllerFactory, mClipboardManager);
+ mClipboardOverlayControllerFactory, mClipboardManager, mUiEventLogger);
listener.start();
verifyZeroInteractions(mClipboardManager);
+ verifyZeroInteractions(mUiEventLogger);
}
@Test
@@ -97,9 +101,10 @@ public class ClipboardListenerTest extends SysuiTestCase {
mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
"true", false);
ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
- mClipboardOverlayControllerFactory, mClipboardManager);
+ mClipboardOverlayControllerFactory, mClipboardManager, mUiEventLogger);
listener.start();
verify(mClipboardManager).addPrimaryClipChangedListener(any());
+ verifyZeroInteractions(mUiEventLogger);
}
@Test
@@ -107,7 +112,7 @@ public class ClipboardListenerTest extends SysuiTestCase {
mDeviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
"true", false);
ClipboardListener listener = new ClipboardListener(getContext(), mDeviceConfigProxy,
- mClipboardOverlayControllerFactory, mClipboardManager);
+ mClipboardOverlayControllerFactory, mClipboardManager, mUiEventLogger);
listener.start();
listener.onPrimaryClipChanged();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEventTest.java b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEventTest.java
new file mode 100644
index 000000000000..c7c2cd8d7b4b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/clipboardoverlay/ClipboardOverlayEventTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 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.clipboardoverlay;
+
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLIPBOARD_OVERLAY_ENABLED;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.provider.DeviceConfig;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.DeviceConfigProxyFake;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ClipboardOverlayEventTest extends SysuiTestCase {
+
+ @Mock
+ private ClipboardManager mClipboardManager;
+ @Mock
+ private ClipboardOverlayControllerFactory mClipboardOverlayControllerFactory;
+ @Mock
+ private ClipboardOverlayController mOverlayController;
+ @Mock
+ private UiEventLogger mUiEventLogger;
+
+ private final String mSampleSource = "Example source";
+
+ private ClipboardListener mClipboardListener;
+
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ when(mClipboardOverlayControllerFactory.create(any())).thenReturn(
+ mOverlayController);
+ when(mClipboardManager.hasPrimaryClip()).thenReturn(true);
+
+ ClipData sampleClipData = new ClipData("Test", new String[]{"text/plain"},
+ new ClipData.Item("Test Item"));
+ when(mClipboardManager.getPrimaryClip()).thenReturn(sampleClipData);
+ when(mClipboardManager.getPrimaryClipSource()).thenReturn(mSampleSource);
+
+ DeviceConfigProxyFake deviceConfigProxy = new DeviceConfigProxyFake();
+ deviceConfigProxy.setProperty(DeviceConfig.NAMESPACE_SYSTEMUI, CLIPBOARD_OVERLAY_ENABLED,
+ "true", false);
+
+ mClipboardListener = new ClipboardListener(getContext(), deviceConfigProxy,
+ mClipboardOverlayControllerFactory, mClipboardManager, mUiEventLogger);
+ }
+
+ @Test
+ public void test_enterAndReenter() {
+ mClipboardListener.start();
+
+ mClipboardListener.onPrimaryClipChanged();
+ mClipboardListener.onPrimaryClipChanged();
+
+ verify(mUiEventLogger, times(1)).log(
+ ClipboardOverlayEvent.CLIPBOARD_OVERLAY_ENTERED, 0, mSampleSource);
+ verify(mUiEventLogger, times(1)).log(
+ ClipboardOverlayEvent.CLIPBOARD_OVERLAY_UPDATED, 0, mSampleSource);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
index b536bfdb944e..2effaec58a86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/decor/RoundedCornerResDelegateTest.kt
@@ -75,7 +75,7 @@ class RoundedCornerResDelegateTest : SysuiTestCase() {
fun testUpdateTuningSizeFactor() {
mContext.orCreateTestableResources.addOverrides(
mockTypeArray = mockTypedArray,
- radiusTop = 0,
+ radiusTop = 2,
radiusBottom = 0,
multipleRadius = false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
index 629c531f0a56..74cf49758ac6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
@@ -166,6 +166,76 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
}
/**
+ * Makes sure swiping up when bouncer initially showing doesn't change the expansion amount.
+ */
+ @Test
+ public void testSwipeUp_whenBouncerInitiallyShowing_keepsExpansionAtZero() {
+ when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
+
+ mTouchHandler.onSessionStart(mTouchSession);
+ ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+ ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+ verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+
+ final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
+
+ final float percent = .3f;
+ final float distanceY = SCREEN_HEIGHT_PX * percent;
+
+ // Swiping up near the top of the screen where the touch initiation region is.
+ final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+ 0, distanceY, 0);
+ final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+ 0, 0, 0);
+
+ assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
+ .isTrue();
+
+ // Ensure only called once
+ verify(mStatusBarKeyguardViewManager)
+ .onPanelExpansionChanged(anyFloat(), anyBoolean(), anyBoolean());
+
+ // TODO(b/227348372): update the logic and also this test.
+ // Ensure the expansion is kept at 0.
+ verify(mStatusBarKeyguardViewManager).onPanelExpansionChanged(eq(0f), eq(false),
+ eq(true));
+ }
+
+ /**
+ * Makes sure swiping down when bouncer initially hidden doesn't change the expansion amount.
+ */
+ @Test
+ public void testSwipeDown_whenBouncerInitiallyHidden_keepsExpansionAtOne() {
+ mTouchHandler.onSessionStart(mTouchSession);
+ ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+ ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+ verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+
+ final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
+
+ final float percent = .15f;
+ final float distanceY = SCREEN_HEIGHT_PX * percent;
+
+ // Swiping down near the bottom of the screen where the touch initiation region is.
+ final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+ 0, SCREEN_HEIGHT_PX - distanceY, 0);
+ final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+ 0, SCREEN_HEIGHT_PX, 0);
+
+ assertThat(gestureListener.onScroll(event1, event2, 0, distanceY))
+ .isTrue();
+
+ // Ensure only called once
+ verify(mStatusBarKeyguardViewManager)
+ .onPanelExpansionChanged(anyFloat(), anyBoolean(), anyBoolean());
+
+ // TODO(b/227348372): update the logic and also this test.
+ // Ensure the expansion is kept at 1.
+ verify(mStatusBarKeyguardViewManager).onPanelExpansionChanged(eq(1f), eq(false),
+ eq(true));
+ }
+
+ /**
* Makes sure the expansion amount is proportional to (1 - scroll).
*/
@Test
@@ -176,12 +246,13 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
- verifyScroll(.3f, Direction.UP, true, gestureListener);
+
+ verifyScroll(.3f, Direction.UP, false, gestureListener);
// Ensure that subsequent gestures are treated as expanding even if the bouncer state
// changes.
when(mCentralSurfaces.isBouncerShowing()).thenReturn(true);
- verifyScroll(.7f, Direction.UP, true, gestureListener);
+ verifyScroll(.7f, Direction.UP, false, gestureListener);
}
/**
@@ -197,17 +268,17 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
final OnGestureListener gestureListener = gestureListenerCaptor.getValue();
- verifyScroll(.3f, Direction.DOWN, false, gestureListener);
+
+ verifyScroll(.3f, Direction.DOWN, true, gestureListener);
// Ensure that subsequent gestures are treated as collapsing even if the bouncer state
// changes.
when(mCentralSurfaces.isBouncerShowing()).thenReturn(false);
- verifyScroll(.7f, Direction.DOWN, false, gestureListener);
+ verifyScroll(.7f, Direction.DOWN, true, gestureListener);
}
- private void verifyScroll(float percent, Direction direction, boolean expanding,
- android.view.GestureDetector.OnGestureListener gestureListener) {
-
+ private void verifyScroll(float percent, Direction direction,
+ boolean isBouncerInitiallyShowing, GestureDetector.OnGestureListener gestureListener) {
final float distanceY = SCREEN_HEIGHT_PX * percent;
final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
@@ -223,10 +294,11 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
verify(mStatusBarKeyguardViewManager)
.onPanelExpansionChanged(anyFloat(), anyBoolean(), anyBoolean());
+ final float expansion = isBouncerInitiallyShowing ? percent : 1 - percent;
+
// Ensure correct expansion passed in.
- verify(mStatusBarKeyguardViewManager)
- .onPanelExpansionChanged(
- eq(expanding ? 1 - percent : percent), eq(false), eq(true));
+ verify(mStatusBarKeyguardViewManager).onPanelExpansionChanged(eq(expansion), eq(false),
+ eq(true));
}
/**
@@ -340,9 +412,9 @@ public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
mTouchHandler.onSessionStart(mTouchSession);
ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+ verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
ArgumentCaptor<InputChannelCompat.InputEventListener> inputEventListenerCaptor =
ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
- verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
verify(mTouchSession).registerInputListener(inputEventListenerCaptor.capture());
when(mVelocityTracker.getYVelocity()).thenReturn(velocityY);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt
index 0787fd65eae1..e3cd90b13422 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/SquigglyProgressTest.kt
@@ -8,6 +8,7 @@ import android.graphics.Rect
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
+import com.android.internal.graphics.ColorUtils
import com.android.systemui.SysuiTestCase
import com.android.systemui.util.mockito.any
import com.google.common.truth.Truth.assertThat
@@ -113,6 +114,7 @@ class SquigglyProgressTest : SysuiTestCase() {
linePaintCaptor.capture())
assertThat(wavePaintCaptor.value.color).isEqualTo(tint)
- assertThat(linePaintCaptor.value.color).isEqualTo(tint)
+ assertThat(linePaintCaptor.value.color).isEqualTo(
+ ColorUtils.setAlphaComponent(tint, DISABLED_ALPHA))
}
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 534c7e7f2029..777198b43d4a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -14,37 +14,41 @@
package com.android.systemui.qs;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.Fragment;
import android.content.Context;
+import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.testing.AndroidTestingRunner;
-import android.testing.LayoutInflaterBuilder;
-import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
+import android.view.LayoutInflater;
import android.view.View;
-import android.widget.FrameLayout;
+import android.view.ViewGroup;
import androidx.test.filters.SmallTest;
-import androidx.test.filters.Suppress;
-import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
-import com.android.keyguard.CarrierText;
-import com.android.systemui.Dependency;
+import com.android.keyguard.BouncerPanelExpansionCalculator;
+import com.android.systemui.R;
import com.android.systemui.SysuiBaseFragmentTest;
+import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
import com.android.systemui.qs.external.CustomTileStatePersister;
import com.android.systemui.qs.external.TileLifecycleManager;
@@ -54,19 +58,18 @@ import com.android.systemui.qs.tileimpl.QSFactoryImpl;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.AutoTileManager;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.policy.Clock;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
import com.android.systemui.tuner.TunerService;
+import com.android.systemui.util.animation.UniqueObjectHostView;
import com.android.systemui.util.settings.SecureSettings;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -75,77 +78,69 @@ import org.mockito.MockitoAnnotations;
import java.util.Optional;
@RunWith(AndroidTestingRunner.class)
-@RunWithLooper
+@RunWithLooper(setAsMainLooper = true)
@SmallTest
-@Suppress
public class QSFragmentTest extends SysuiBaseFragmentTest {
- private MetricsLogger mMockMetricsLogger;
- @Mock
- private QSFragmentComponent.Factory mQsComponentFactory;
- @Mock
- private QSFragmentComponent mQsFragmentComponent;
- @Mock
- private QSPanelController mQSPanelController;
- @Mock
- private MediaHost mQSMediaHost;
- @Mock
- private MediaHost mQQSMediaHost;
- @Mock
- private KeyguardBypassController mBypassController;
- @Mock
- private FalsingManager mFalsingManager;
- @Mock
- private TileServiceRequestController.Builder mTileServiceRequestControllerBuilder;
- @Mock
- private TileServiceRequestController mTileServiceRequestController;
+ @Mock private QSFragmentComponent.Factory mQsComponentFactory;
+ @Mock private QSFragmentComponent mQsFragmentComponent;
+ @Mock private QSPanelController mQSPanelController;
+ @Mock private MediaHost mQSMediaHost;
+ @Mock private MediaHost mQQSMediaHost;
+ @Mock private KeyguardBypassController mBypassController;
+ @Mock private FalsingManager mFalsingManager;
+ @Mock private TileServiceRequestController.Builder mTileServiceRequestControllerBuilder;
+ @Mock private TileServiceRequestController mTileServiceRequestController;
+ @Mock private QSCustomizerController mQsCustomizerController;
+ @Mock private QuickQSPanelController mQuickQSPanelController;
+ @Mock private FooterActionsController mQSFooterActionController;
+ @Mock private QSContainerImplController mQSContainerImplController;
+ @Mock private QSContainerImpl mContainer;
+ @Mock private QSFooter mFooter;
+ @Mock private LayoutInflater mLayoutInflater;
+ @Mock private NonInterceptingScrollView mQSPanelScrollView;
+ @Mock private QuickStatusBarHeader mHeader;
+ @Mock private QSPanel.QSTileLayout mQsTileLayout;
+ @Mock private QSPanel.QSTileLayout mQQsTileLayout;
+ @Mock private QSAnimator mQSAnimator;
+ private View mQsFragmentView;
+ @Mock private StatusBarStateController mStatusBarStateController;
public QSFragmentTest() {
super(QSFragment.class);
- injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
}
@Before
- @Ignore("failing")
- public void addLeakCheckDependencies() {
- MockitoAnnotations.initMocks(this);
- when(mQsComponentFactory.create(any(QSFragment.class))).thenReturn(mQsFragmentComponent);
- when(mQsFragmentComponent.getQSPanelController()).thenReturn(mQSPanelController);
-
- when(mTileServiceRequestControllerBuilder.create(any()))
- .thenReturn(mTileServiceRequestController);
-
- mMockMetricsLogger = mDependency.injectMockDependency(MetricsLogger.class);
- mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE,
- new LayoutInflaterBuilder(mContext)
- .replace("com.android.systemui.statusbar.policy.SplitClockView",
- FrameLayout.class)
- .replace("TextClock", View.class)
- .replace(CarrierText.class, View.class)
- .replace(Clock.class, View.class)
- .build());
-
- mDependency.injectTestDependency(Dependency.BG_LOOPER,
- TestableLooper.get(this).getLooper());
- mDependency.injectMockDependency(UserSwitcherController.class);
+ public void setup() {
+ injectLeakCheckedDependencies(ALL_SUPPORTED_CLASSES);
}
@Test
- @Ignore("failing")
public void testListening() {
- assertEquals(Looper.myLooper(), Looper.getMainLooper());
QSFragment qs = (QSFragment) mFragment;
mFragments.dispatchResume();
processAllMessages();
- QSTileHost host = new QSTileHost(mContext, mock(StatusBarIconController.class),
- mock(QSFactoryImpl.class), new Handler(), Looper.myLooper(),
- mock(PluginManager.class), mock(TunerService.class),
- () -> mock(AutoTileManager.class), mock(DumpManager.class),
- mock(BroadcastDispatcher.class), Optional.of(mock(CentralSurfaces.class)),
- mock(QSLogger.class), mock(UiEventLogger.class), mock(UserTracker.class),
- mock(SecureSettings.class), mock(CustomTileStatePersister.class),
- mTileServiceRequestControllerBuilder, mock(TileLifecycleManager.Factory.class));
+ QSTileHost host =
+ new QSTileHost(
+ mContext,
+ mock(StatusBarIconController.class),
+ mock(QSFactoryImpl.class),
+ new Handler(),
+ Looper.myLooper(),
+ mock(PluginManager.class),
+ mock(TunerService.class),
+ () -> mock(AutoTileManager.class),
+ mock(DumpManager.class),
+ mock(BroadcastDispatcher.class),
+ Optional.of(mock(CentralSurfaces.class)),
+ mock(QSLogger.class),
+ mock(UiEventLogger.class),
+ mock(UserTracker.class),
+ mock(SecureSettings.class),
+ mock(CustomTileStatePersister.class),
+ mTileServiceRequestControllerBuilder,
+ mock(TileLifecycleManager.Factory.class));
qs.setListening(true);
processAllMessages();
@@ -157,13 +152,11 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
}
@Test
- @Ignore("failing")
public void testSaveState() {
- QSFragment qs = (QSFragment) mFragment;
-
mFragments.dispatchResume();
processAllMessages();
+ QSFragment qs = (QSFragment) mFragment;
qs.setListening(true);
qs.setExpanded(true);
processAllMessages();
@@ -176,14 +169,91 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
assertTrue(qs.isExpanded());
}
+ @Test
+ public void transitionToFullShade_inSplitShade_setsAlphaBasedOnProgress() {
+ QSFragment fragment = resumeAndGetFragment();
+ enableSplitShade();
+ int transitionPxAmount = 123;
+ float transitionProgress = 0.5f;
+
+ fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+
+ assertThat(mQsFragmentView.getAlpha())
+ .isEqualTo(ShadeInterpolation.getContentAlpha(transitionProgress));
+ }
+
+ @Test
+ public void
+ transitionToFullShade_inSplitShade_onKeyguard_bouncerNotActive_usesShadeInterpolator() {
+ QSFragment fragment = resumeAndGetFragment();
+ enableSplitShade();
+ setStatusBarState(StatusBarState.KEYGUARD);
+ when(mQSPanelController.bouncerInTransit()).thenReturn(false);
+ int transitionPxAmount = 123;
+ float transitionProgress = 0.5f;
+
+ fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+
+ assertThat(mQsFragmentView.getAlpha())
+ .isEqualTo(ShadeInterpolation.getContentAlpha(transitionProgress));
+ }
+
+ @Test
+ public void
+ transitionToFullShade_inSplitShade_onKeyguard_bouncerActive_usesBouncerInterpolator() {
+ QSFragment fragment = resumeAndGetFragment();
+ enableSplitShade();
+ setStatusBarState(StatusBarState.KEYGUARD);
+ when(mQSPanelController.bouncerInTransit()).thenReturn(true);
+ int transitionPxAmount = 123;
+ float transitionProgress = 0.5f;
+
+ fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+
+ assertThat(mQsFragmentView.getAlpha())
+ .isEqualTo(
+ BouncerPanelExpansionCalculator.getBackScrimScaledExpansion(
+ transitionProgress));
+ }
+
+ @Test
+ public void transitionToFullShade_notInSplitShade_alwaysSetsAlphaTo1() {
+ QSFragment fragment = resumeAndGetFragment();
+ disableSplitShade();
+
+ int transitionPxAmount = 12;
+ float transitionProgress = 0.1f;
+ fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+ assertThat(mQsFragmentView.getAlpha()).isEqualTo(1);
+
+ transitionPxAmount = 123;
+ transitionProgress = 0.5f;
+ fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+ assertThat(mQsFragmentView.getAlpha()).isEqualTo(1);
+ assertThat(mQsFragmentView.getAlpha()).isEqualTo(1);
+
+ transitionPxAmount = 234;
+ transitionProgress = 0.7f;
+ fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress);
+ assertThat(mQsFragmentView.getAlpha()).isEqualTo(1);
+ }
+
@Override
protected Fragment instantiate(Context context, String className, Bundle arguments) {
+ MockitoAnnotations.initMocks(this);
CommandQueue commandQueue = new CommandQueue(context);
+
+ setupQsComponent();
+ setUpViews();
+ setUpInflater();
+ setUpMedia();
+ setUpOther();
+
return new QSFragment(
- new RemoteInputQuickSettingsDisabler(context, commandQueue,
- mock(ConfigurationController.class)),
+ new RemoteInputQuickSettingsDisabler(
+ context, commandQueue, mock(ConfigurationController.class)),
mock(QSTileHost.class),
- mock(StatusBarStateController.class),
+ mStatusBarStateController,
commandQueue,
mQSMediaHost,
mQQSMediaHost,
@@ -193,4 +263,73 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
mFalsingManager,
mock(DumpManager.class));
}
+
+ private void setUpOther() {
+ when(mTileServiceRequestControllerBuilder.create(any()))
+ .thenReturn(mTileServiceRequestController);
+ when(mQSContainerImplController.getView()).thenReturn(mContainer);
+ when(mQSPanelController.getTileLayout()).thenReturn(mQQsTileLayout);
+ when(mQuickQSPanelController.getTileLayout()).thenReturn(mQsTileLayout);
+ }
+
+ private void setUpMedia() {
+ when(mQSMediaHost.getCurrentClipping()).thenReturn(new Rect());
+ when(mQSMediaHost.getHostView()).thenReturn(new UniqueObjectHostView(mContext));
+ when(mQQSMediaHost.getHostView()).thenReturn(new UniqueObjectHostView(mContext));
+ }
+
+ private void setUpViews() {
+ mQsFragmentView = spy(new View(mContext));
+ when(mQsFragmentView.findViewById(R.id.expanded_qs_scroll_view))
+ .thenReturn(mQSPanelScrollView);
+ when(mQsFragmentView.findViewById(R.id.header)).thenReturn(mHeader);
+ when(mQsFragmentView.findViewById(android.R.id.edit)).thenReturn(new View(mContext));
+ }
+
+ private void setUpInflater() {
+ when(mLayoutInflater.cloneInContext(any(Context.class))).thenReturn(mLayoutInflater);
+ when(mLayoutInflater.inflate(anyInt(), any(ViewGroup.class), anyBoolean()))
+ .thenReturn(mQsFragmentView);
+ mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, mLayoutInflater);
+ }
+
+ private void setupQsComponent() {
+ when(mQsComponentFactory.create(any(QSFragment.class))).thenReturn(mQsFragmentComponent);
+ when(mQsFragmentComponent.getQSPanelController()).thenReturn(mQSPanelController);
+ when(mQsFragmentComponent.getQuickQSPanelController()).thenReturn(mQuickQSPanelController);
+ when(mQsFragmentComponent.getQSCustomizerController()).thenReturn(mQsCustomizerController);
+ when(mQsFragmentComponent.getQSContainerImplController())
+ .thenReturn(mQSContainerImplController);
+ when(mQsFragmentComponent.getQSFooter()).thenReturn(mFooter);
+ when(mQsFragmentComponent.getQSFooterActionController())
+ .thenReturn(mQSFooterActionController);
+ when(mQsFragmentComponent.getQSAnimator()).thenReturn(mQSAnimator);
+ }
+
+ private QSFragment getFragment() {
+ return ((QSFragment) mFragment);
+ }
+
+ private QSFragment resumeAndGetFragment() {
+ mFragments.dispatchResume();
+ processAllMessages();
+ return getFragment();
+ }
+
+ private void setStatusBarState(int statusBarState) {
+ when(mStatusBarStateController.getState()).thenReturn(statusBarState);
+ getFragment().onStateChanged(statusBarState);
+ }
+
+ private void enableSplitShade() {
+ setSplitShadeEnabled(true);
+ }
+
+ private void disableSplitShade() {
+ setSplitShadeEnabled(false);
+ }
+
+ private void setSplitShadeEnabled(boolean enabled) {
+ getFragment().setInSplitShade(enabled);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
index e9488e9ad98c..58a070db9a95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
@@ -15,7 +15,9 @@ import com.android.systemui.qs.customize.QSCustomizerController
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.settings.brightness.BrightnessController
import com.android.systemui.settings.brightness.BrightnessSliderController
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.systemui.tuner.TunerService
+import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
@@ -52,6 +54,7 @@ class QSPanelControllerTest : SysuiTestCase() {
@Mock private lateinit var mediaHost: MediaHost
@Mock private lateinit var tile: QSTile
@Mock private lateinit var otherTile: QSTile
+ @Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
private lateinit var controller: QSPanelController
@@ -62,6 +65,7 @@ class QSPanelControllerTest : SysuiTestCase() {
whenever(brightnessSliderFactory.create(any(), any())).thenReturn(brightnessSlider)
whenever(brightnessControllerFactory.create(any())).thenReturn(brightnessController)
whenever(qsPanel.resources).thenReturn(mContext.orCreateTestableResources.resources)
+ whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false)
controller = QSPanelController(
qsPanel,
@@ -80,7 +84,8 @@ class QSPanelControllerTest : SysuiTestCase() {
brightnessControllerFactory,
brightnessSliderFactory,
falsingManager,
- featureFlags
+ featureFlags,
+ statusBarKeyguardViewManager
)
}
@@ -109,4 +114,12 @@ class QSPanelControllerTest : SysuiTestCase() {
verify(tile).refreshState()
verify(otherTile, Mockito.never()).refreshState()
}
+
+ @Test
+ fun testBouncerIsInTransit() {
+ whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true)
+ assertThat(controller.bouncerInTransit()).isEqualTo(true)
+ whenever(statusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(false)
+ assertThat(controller.bouncerInTransit()).isEqualTo(false)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index 5eef1df8c7a3..81a5f11b1553 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -119,6 +119,8 @@ public class ScrimControllerTest extends SysuiTestCase {
// event-dispatch-on-registration pattern caused some of these unit tests to fail.)
@Mock
private PanelExpansionStateManager mPanelExpansionStateManager;
+ @Mock
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private static class AnimatorListener implements Animator.AnimatorListener {
@@ -233,7 +235,8 @@ public class ScrimControllerTest extends SysuiTestCase {
mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
mScreenOffAnimationController,
mPanelExpansionStateManager,
- mKeyguardUnlockAnimationController);
+ mKeyguardUnlockAnimationController,
+ mStatusBarKeyguardViewManager);
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
mScrimController.setAnimatorListener(mAnimatorListener);
@@ -1234,6 +1237,8 @@ public class ScrimControllerTest extends SysuiTestCase {
@Test
public void testNotificationTransparency_followsPanelExpansionInShadeLockedState() {
+ when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true);
+
mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 0f, /* expansion */ 0.8f);
@@ -1242,6 +1247,8 @@ public class ScrimControllerTest extends SysuiTestCase {
@Test
public void testNotificationTransparency_unnocclusion() {
+ when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true);
+
mScrimController.transitionTo(ScrimState.KEYGUARD);
mScrimController.setUnocclusionAnimationRunning(true);
@@ -1255,6 +1262,8 @@ public class ScrimControllerTest extends SysuiTestCase {
@Test
public void testNotificationTransparency_inKeyguardState() {
+ when(mStatusBarKeyguardViewManager.bouncerIsInTransit()).thenReturn(true);
+
mScrimController.transitionTo(ScrimState.KEYGUARD);
assertAlphaAfterExpansion(mNotificationsScrim, /* alpha */ 1f, /* expansion */ 0.8f);
@@ -1351,6 +1360,15 @@ public class ScrimControllerTest extends SysuiTestCase {
));
}
+ @Test
+ public void keyguardGoingAwayUpdateScrims() {
+ when(mKeyguardStateController.isKeyguardGoingAway()).thenReturn(true);
+ mScrimController.updateScrims();
+ finishAnimationsImmediately();
+ assertThat(mNotificationsScrim.getViewAlpha()).isEqualTo(TRANSPARENT);
+ }
+
+
private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
mScrimController.setRawPanelExpansionFraction(expansion);
finishAnimationsImmediately();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index ede3de83b572..90cbf540004e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -55,6 +55,8 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.unfold.SysUIUnfoldComponent;
+import com.google.common.truth.Truth;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -434,4 +436,14 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
verify(mBouncer).updateKeyguardPosition(1.0f);
}
+
+ @Test
+ public void testBouncerIsInTransit() {
+ when(mBouncer.inTransit()).thenReturn(true);
+ Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isTrue();
+ when(mBouncer.inTransit()).thenReturn(false);
+ Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isFalse();
+ mBouncer = null;
+ Truth.assertThat(mStatusBarKeyguardViewManager.bouncerIsInTransit()).isFalse();
+ }
}
diff --git a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
index 06fd5c0e9b82..88ad62046b2b 100644
--- a/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
+++ b/services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java
@@ -23,6 +23,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.StringRes;
import android.app.Activity;
@@ -34,7 +35,8 @@ import android.companion.virtual.IVirtualDevice;
import android.companion.virtual.IVirtualDeviceActivityListener;
import android.companion.virtual.VirtualDeviceManager.ActivityListener;
import android.companion.virtual.VirtualDeviceParams;
-import android.companion.virtual.audio.IAudioSessionCallback;
+import android.companion.virtual.audio.IAudioConfigChangedCallback;
+import android.companion.virtual.audio.IAudioRoutingCallback;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -269,7 +271,9 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@Override // Binder call
- public void onAudioSessionStarting(int displayId, IAudioSessionCallback callback) {
+ public void onAudioSessionStarting(int displayId,
+ @NonNull IAudioRoutingCallback routingCallback,
+ @Nullable IAudioConfigChangedCallback configChangedCallback) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
"Permission required to start audio session");
@@ -283,7 +287,8 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
if (mVirtualAudioController == null) {
mVirtualAudioController = new VirtualAudioController(mContext);
GenericWindowPolicyController gwpc = mWindowPolicyControllers.get(displayId);
- mVirtualAudioController.startListening(gwpc, callback);
+ mVirtualAudioController.startListening(gwpc, routingCallback,
+ configChangedCallback);
}
}
}
diff --git a/services/companion/java/com/android/server/companion/virtual/audio/AudioPlaybackDetector.java b/services/companion/java/com/android/server/companion/virtual/audio/AudioPlaybackDetector.java
index 2d7291300e23..6e82d6672cd4 100644
--- a/services/companion/java/com/android/server/companion/virtual/audio/AudioPlaybackDetector.java
+++ b/services/companion/java/com/android/server/companion/virtual/audio/AudioPlaybackDetector.java
@@ -51,8 +51,10 @@ final class AudioPlaybackDetector extends AudioManager.AudioPlaybackCallback {
}
void unregister() {
- mAudioPlaybackCallback = null;
- mAudioManager.unregisterAudioPlaybackCallback(/* cb= */ this);
+ if (mAudioPlaybackCallback != null) {
+ mAudioPlaybackCallback = null;
+ mAudioManager.unregisterAudioPlaybackCallback(/* cb= */ this);
+ }
}
@Override
diff --git a/services/companion/java/com/android/server/companion/virtual/audio/AudioRecordingDetector.java b/services/companion/java/com/android/server/companion/virtual/audio/AudioRecordingDetector.java
index c20414529f5b..54add2e1fc85 100644
--- a/services/companion/java/com/android/server/companion/virtual/audio/AudioRecordingDetector.java
+++ b/services/companion/java/com/android/server/companion/virtual/audio/AudioRecordingDetector.java
@@ -51,8 +51,10 @@ final class AudioRecordingDetector extends AudioManager.AudioRecordingCallback {
}
void unregister() {
- mAudioRecordingCallback = null;
- mAudioManager.unregisterAudioRecordingCallback(/* cb= */ this);
+ if (mAudioRecordingCallback != null) {
+ mAudioRecordingCallback = null;
+ mAudioManager.unregisterAudioRecordingCallback(/* cb= */ this);
+ }
}
@Override
diff --git a/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java b/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java
index 1dc87d68aeae..13a47d681729 100644
--- a/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java
+++ b/services/companion/java/com/android/server/companion/virtual/audio/VirtualAudioController.java
@@ -21,7 +21,8 @@ import static android.media.AudioPlaybackConfiguration.PLAYER_STATE_STARTED;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
-import android.companion.virtual.audio.IAudioSessionCallback;
+import android.companion.virtual.audio.IAudioConfigChangedCallback;
+import android.companion.virtual.audio.IAudioRoutingCallback;
import android.content.Context;
import android.media.AudioManager;
import android.media.AudioPlaybackConfiguration;
@@ -64,9 +65,10 @@ public final class VirtualAudioController implements AudioPlaybackCallback,
private ArraySet<Integer> mPlayingAppUids = new ArraySet<>();
private GenericWindowPolicyController mGenericWindowPolicyController;
private final Object mCallbackLock = new Object();
- @Nullable
@GuardedBy("mCallbackLock")
- private IAudioSessionCallback mCallback;
+ private IAudioRoutingCallback mRoutingCallback;
+ @GuardedBy("mCallbackLock")
+ private IAudioConfigChangedCallback mConfigChangedCallback;
public VirtualAudioController(Context context) {
mContext = context;
@@ -80,18 +82,22 @@ public final class VirtualAudioController implements AudioPlaybackCallback,
*/
public void startListening(
@NonNull GenericWindowPolicyController genericWindowPolicyController,
- @Nullable IAudioSessionCallback callback) {
+ @NonNull IAudioRoutingCallback routingCallback,
+ @Nullable IAudioConfigChangedCallback configChangedCallback) {
mGenericWindowPolicyController = genericWindowPolicyController;
mGenericWindowPolicyController.setRunningAppsChangedListener(/* listener= */ this);
synchronized (mCallbackLock) {
- mCallback = callback;
+ mRoutingCallback = routingCallback;
+ mConfigChangedCallback = configChangedCallback;
}
synchronized (mLock) {
mRunningAppUids.clear();
mPlayingAppUids.clear();
}
- mAudioPlaybackDetector.register(/* callback= */ this);
- mAudioRecordingDetector.register(/* callback= */ this);
+ if (configChangedCallback != null) {
+ mAudioPlaybackDetector.register(/* callback= */ this);
+ mAudioRecordingDetector.register(/* callback= */ this);
+ }
}
/**
@@ -109,7 +115,8 @@ public final class VirtualAudioController implements AudioPlaybackCallback,
mGenericWindowPolicyController = null;
}
synchronized (mCallbackLock) {
- mCallback = null;
+ mRoutingCallback = null;
+ mConfigChangedCallback = null;
}
}
@@ -169,9 +176,9 @@ public final class VirtualAudioController implements AudioPlaybackCallback,
audioPlaybackConfigurations = findPlaybackConfigurations(configs, mRunningAppUids);
}
synchronized (mCallbackLock) {
- if (mCallback != null) {
+ if (mConfigChangedCallback != null) {
try {
- mCallback.onPlaybackConfigChanged(audioPlaybackConfigurations);
+ mConfigChangedCallback.onPlaybackConfigChanged(audioPlaybackConfigurations);
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException when calling onPlaybackConfigChanged", e);
}
@@ -188,9 +195,9 @@ public final class VirtualAudioController implements AudioPlaybackCallback,
audioRecordingConfigurations = findRecordingConfigurations(configs, mRunningAppUids);
}
synchronized (mCallbackLock) {
- if (mCallback != null) {
+ if (mConfigChangedCallback != null) {
try {
- mCallback.onRecordingConfigChanged(audioRecordingConfigurations);
+ mConfigChangedCallback.onRecordingConfigChanged(audioRecordingConfigurations);
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException when calling onRecordingConfigChanged", e);
}
@@ -227,9 +234,9 @@ public final class VirtualAudioController implements AudioPlaybackCallback,
}
synchronized (mCallbackLock) {
- if (mCallback != null) {
+ if (mRoutingCallback != null) {
try {
- mCallback.onAppsNeedingAudioRoutingChanged(runningUids);
+ mRoutingCallback.onAppsNeedingAudioRoutingChanged(runningUids);
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException when calling updateReroutingApps", e);
}
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 68cd28809fd0..f34c5062144e 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -43,6 +43,7 @@ import android.util.ArraySet;
import android.util.SparseArray;
import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.pm.KnownPackages;
import com.android.server.pm.PackageList;
import com.android.server.pm.PackageSetting;
import com.android.server.pm.dex.DynamicCodeLogger;
@@ -68,51 +69,6 @@ import java.util.function.Consumer;
* @hide Only for use within the system server.
*/
public abstract class PackageManagerInternal {
-
- @IntDef(prefix = "PACKAGE_", value = {
- PACKAGE_SYSTEM,
- PACKAGE_SETUP_WIZARD,
- PACKAGE_INSTALLER,
- PACKAGE_UNINSTALLER,
- PACKAGE_VERIFIER,
- PACKAGE_BROWSER,
- PACKAGE_SYSTEM_TEXT_CLASSIFIER,
- PACKAGE_PERMISSION_CONTROLLER,
- PACKAGE_CONFIGURATOR,
- PACKAGE_INCIDENT_REPORT_APPROVER,
- PACKAGE_APP_PREDICTOR,
- PACKAGE_OVERLAY_CONFIG_SIGNATURE,
- PACKAGE_WIFI,
- PACKAGE_COMPANION,
- PACKAGE_RETAIL_DEMO,
- PACKAGE_RECENTS,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface KnownPackage {}
-
- public static final int PACKAGE_SYSTEM = 0;
- public static final int PACKAGE_SETUP_WIZARD = 1;
- public static final int PACKAGE_INSTALLER = 2;
- public static final int PACKAGE_UNINSTALLER = 3;
- public static final int PACKAGE_VERIFIER = 4;
- public static final int PACKAGE_BROWSER = 5;
- public static final int PACKAGE_SYSTEM_TEXT_CLASSIFIER = 6;
- public static final int PACKAGE_PERMISSION_CONTROLLER = 7;
- public static final int PACKAGE_WELLBEING = 8;
- public static final int PACKAGE_DOCUMENTER = 9;
- public static final int PACKAGE_CONFIGURATOR = 10;
- public static final int PACKAGE_INCIDENT_REPORT_APPROVER = 11;
- public static final int PACKAGE_APP_PREDICTOR = 12;
- public static final int PACKAGE_OVERLAY_CONFIG_SIGNATURE = 13;
- public static final int PACKAGE_WIFI = 14;
- public static final int PACKAGE_COMPANION = 15;
- public static final int PACKAGE_RETAIL_DEMO = 16;
- public static final int PACKAGE_RECENTS = 17;
- public static final int PACKAGE_AMBIENT_CONTEXT_DETECTION = 18;
- // Integer value of the last known package ID. Increases as new ID is added to KnownPackage.
- // Please note the numbers should be continuous.
- public static final int LAST_KNOWN_PACKAGE = PACKAGE_AMBIENT_CONTEXT_DETECTION;
-
@LongDef(flag = true, prefix = "RESOLVE_", value = {
RESOLVE_NON_BROWSER_ONLY,
RESOLVE_NON_RESOLVER_ONLY
@@ -754,12 +710,11 @@ public abstract class PackageManagerInternal {
*/
public abstract boolean isResolveActivityComponent(@NonNull ComponentInfo component);
-
/**
* Returns a list of package names for a known package
*/
public abstract @NonNull String[] getKnownPackageNames(
- @KnownPackage int knownPackage, int userId);
+ @KnownPackages.KnownPackage int knownPackage, int userId);
/**
* Returns whether the package is an instant app.
@@ -1143,55 +1098,6 @@ public abstract class PackageManagerInternal {
@NonNull InstalledLoadingProgressCallback callback, int userId);
/**
- * Returns the string representation of a known package. For example,
- * {@link #PACKAGE_SETUP_WIZARD} is represented by the string Setup Wizard.
- *
- * @param knownPackage The known package.
- * @return The string representation.
- */
- public static @NonNull String knownPackageToString(@KnownPackage int knownPackage) {
- switch (knownPackage) {
- case PACKAGE_SYSTEM:
- return "System";
- case PACKAGE_SETUP_WIZARD:
- return "Setup Wizard";
- case PACKAGE_INSTALLER:
- return "Installer";
- case PACKAGE_UNINSTALLER:
- return "Uninstaller";
- case PACKAGE_VERIFIER:
- return "Verifier";
- case PACKAGE_BROWSER:
- return "Browser";
- case PACKAGE_SYSTEM_TEXT_CLASSIFIER:
- return "System Text Classifier";
- case PACKAGE_PERMISSION_CONTROLLER:
- return "Permission Controller";
- case PACKAGE_WELLBEING:
- return "Wellbeing";
- case PACKAGE_DOCUMENTER:
- return "Documenter";
- case PACKAGE_CONFIGURATOR:
- return "Configurator";
- case PACKAGE_INCIDENT_REPORT_APPROVER:
- return "Incident Report Approver";
- case PACKAGE_APP_PREDICTOR:
- return "App Predictor";
- case PACKAGE_WIFI:
- return "Wi-Fi";
- case PACKAGE_COMPANION:
- return "Companion";
- case PACKAGE_RETAIL_DEMO:
- return "Retail Demo";
- case PACKAGE_OVERLAY_CONFIG_SIGNATURE:
- return "Overlay Config Signature";
- case PACKAGE_RECENTS:
- return "Recents";
- }
- return "Unknown";
- }
-
- /**
* Callback to listen for loading progress of a package installed on Incremental File System.
*/
public abstract static class InstalledLoadingProgressCallback {
diff --git a/services/core/java/com/android/server/AlarmManagerInternal.java b/services/core/java/com/android/server/AlarmManagerInternal.java
index e5ae77a26246..e3c8afabcf6f 100644
--- a/services/core/java/com/android/server/AlarmManagerInternal.java
+++ b/services/core/java/com/android/server/AlarmManagerInternal.java
@@ -44,7 +44,8 @@ public interface AlarmManagerInternal {
/**
* Returns if the given package in the given user holds
- * {@link android.Manifest.permission#SCHEDULE_EXACT_ALARM}
+ * {@link android.Manifest.permission#SCHEDULE_EXACT_ALARM} or
+ * {@link android.Manifest.permission#USE_EXACT_ALARM}.
*/
- boolean hasScheduleExactAlarm(String packageName, int uid);
+ boolean hasExactAlarmPermission(String packageName, int uid);
}
diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java
index 690051f47326..0cbc7ad404f5 100644
--- a/services/core/java/com/android/server/am/AppBatteryTracker.java
+++ b/services/core/java/com/android/server/am/AppBatteryTracker.java
@@ -20,6 +20,7 @@ import static android.Manifest.permission.ACCESS_BACKGROUND_LOCATION;
import static android.app.ActivityManager.RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
import static android.app.ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
import static android.app.ActivityManager.RESTRICTION_LEVEL_RESTRICTED_BUCKET;
+import static android.app.ActivityManager.RESTRICTION_LEVEL_UNKNOWN;
import static android.app.ActivityManager.isLowRamDeviceStatic;
import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_SYSTEM;
import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
@@ -1119,6 +1120,13 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "current_drain_high_threshold_by_bg_location";
/**
+ * Whether or not the battery usage of the offending app should fulfill the 1st threshold
+ * before taking actions for the 2nd threshold.
+ */
+ static final String KEY_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLDS =
+ DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "current_drain_decouple_thresholds";
+
+ /**
* Default value to the {@link #INDEX_REGULAR_CURRENT_DRAIN_THRESHOLD} of
* the {@link #mBgCurrentDrainRestrictedBucketThreshold}.
*/
@@ -1191,6 +1199,11 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
final boolean mDefaultBgCurrentDrainHighThresholdByBgLocation;
/**
+ * Default value to {@link #mBgCurrentDrainDecoupleThresholds}.
+ */
+ static final boolean DEFAULT_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLD = true;
+
+ /**
* The index to {@link #mBgCurrentDrainRestrictedBucketThreshold}
* and {@link #mBgCurrentDrainBgRestrictedThreshold}.
*/
@@ -1258,6 +1271,11 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
volatile boolean mBgCurrentDrainHighThresholdByBgLocation;
/**
+ * @see #KEY_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLDS.
+ */
+ volatile boolean mBgCurrentDrainDecoupleThresholds;
+
+ /**
* The capacity of the battery when fully charged in mAh.
*/
private int mBatteryFullChargeMah;
@@ -1369,6 +1387,9 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
case KEY_BG_CURRENT_DRAIN_EXEMPTED_TYPES:
updateCurrentDrainExemptedTypes();
break;
+ case KEY_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLDS:
+ updateCurrentDrainDecoupleThresholds();
+ break;
default:
super.onPropertiesChanged(name);
break;
@@ -1466,6 +1487,13 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
mDefaultBgCurrentDrainExemptedTypes);
}
+ private void updateCurrentDrainDecoupleThresholds() {
+ mBgCurrentDrainDecoupleThresholds = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ KEY_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLDS,
+ DEFAULT_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLD);
+ }
+
@Override
public void onSystemReady() {
mBatteryFullChargeMah =
@@ -1477,20 +1505,30 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
updateCurrentDrainLocationMinDuration();
updateCurrentDrainEventDurationBasedThresholdEnabled();
updateCurrentDrainExemptedTypes();
+ updateCurrentDrainDecoupleThresholds();
}
@Override
- public @RestrictionLevel int getProposedRestrictionLevel(String packageName, int uid) {
+ @RestrictionLevel
+ public int getProposedRestrictionLevel(String packageName, int uid,
+ @RestrictionLevel int maxLevel) {
+ if (maxLevel <= RESTRICTION_LEVEL_ADAPTIVE_BUCKET) {
+ return RESTRICTION_LEVEL_UNKNOWN;
+ }
synchronized (mLock) {
- final int index = mHighBgBatteryPackages.indexOfKey(uid);
- if (index < 0) {
- // Not found, return adaptive as the default one.
- return RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
+ final long[] ts = mHighBgBatteryPackages.get(uid);
+ if (ts != null) {
+ final int restrictedLevel = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] > 0
+ ? RESTRICTION_LEVEL_RESTRICTED_BUCKET
+ : RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
+ if (maxLevel > RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
+ return ts[TIME_STAMP_INDEX_BG_RESTRICTED] > 0
+ ? RESTRICTION_LEVEL_BACKGROUND_RESTRICTED : restrictedLevel;
+ } else if (maxLevel == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
+ return restrictedLevel;
+ }
}
- final long[] ts = mHighBgBatteryPackages.valueAt(index);
- return ts[TIME_STAMP_INDEX_BG_RESTRICTED] > 0
- ? RESTRICTION_LEVEL_BACKGROUND_RESTRICTED
- : RESTRICTION_LEVEL_RESTRICTED_BUCKET;
+ return RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
}
}
@@ -1573,36 +1611,58 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
final int thresholdIndex = getCurrentDrainThresholdIndex(uid, now,
mBgCurrentDrainWindowMs);
final int index = mHighBgBatteryPackages.indexOfKey(uid);
+ final boolean decoupleThresholds = mBgCurrentDrainDecoupleThresholds;
+ final double rbThreshold = mBgCurrentDrainRestrictedBucketThreshold[thresholdIndex];
+ final double brThreshold = mBgCurrentDrainBgRestrictedThreshold[thresholdIndex];
if (index < 0) {
- if (rbPercentage >= mBgCurrentDrainRestrictedBucketThreshold[thresholdIndex]) {
+ long[] ts = null;
+ if (rbPercentage >= rbThreshold) {
// New findings to us, track it and let the controller know.
- final long[] ts = new long[TIME_STAMP_INDEX_LAST];
+ ts = new long[TIME_STAMP_INDEX_LAST];
ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now;
mHighBgBatteryPackages.put(uid, ts);
notifyController = excessive = true;
}
+ if (decoupleThresholds && brPercentage >= brThreshold) {
+ if (ts == null) {
+ ts = new long[TIME_STAMP_INDEX_LAST];
+ mHighBgBatteryPackages.put(uid, ts);
+ }
+ ts[TIME_STAMP_INDEX_BG_RESTRICTED] = now;
+ notifyController = excessive = true;
+ }
} else {
final long[] ts = mHighBgBatteryPackages.valueAt(index);
- if (rbPercentage < mBgCurrentDrainRestrictedBucketThreshold[thresholdIndex]) {
- // it's actually back to normal, but we don't untrack it until
- // explicit user interactions.
- notifyController = true;
+ final long lastRestrictBucketTs = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET];
+ if (rbPercentage >= rbThreshold) {
+ if (lastRestrictBucketTs == 0) {
+ ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now;
+ }
+ notifyController = excessive = true;
} else {
- excessive = true;
- if (brPercentage >= mBgCurrentDrainBgRestrictedThreshold[thresholdIndex]
- && curLevel == RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
- // If we're in the restricted standby bucket but still seeing high
- // current drains, tell the controller again.
- final long lastResbucket = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET];
- final long lastBgRes = ts[TIME_STAMP_INDEX_BG_RESTRICTED];
- // If it has been a while since restricting the app and since the last
- // time we notify the controller, notify it again.
- if ((now >= lastResbucket + mBgCurrentDrainWindowMs) && (lastBgRes == 0
- || (now >= lastBgRes + mBgCurrentDrainWindowMs))) {
- ts[TIME_STAMP_INDEX_BG_RESTRICTED] = now;
- notifyController = true;
- }
+ // It's actually back to normal, but we don't untrack it until
+ // explicit user interactions, because the restriction could be the cause
+ // of going back to normal.
+ }
+ if (brPercentage >= brThreshold) {
+ // If either
+ // a) It's configured to goto threshold 2 directly without threshold 1;
+ // b) It's already in the restricted standby bucket, but still seeing
+ // high current drains, and it's been a while since it's restricted;
+ // tell the controller.
+ notifyController = decoupleThresholds
+ || (curLevel == RESTRICTION_LEVEL_RESTRICTED_BUCKET
+ && (now > lastRestrictBucketTs + mBgCurrentDrainWindowMs));
+ if (notifyController) {
+ ts[TIME_STAMP_INDEX_BG_RESTRICTED] = now;
}
+ excessive = true;
+ } else {
+ // Reset the track now - if it's already background restricted, it requires
+ // user consent to unrestrict it; or if it's in restricted bucket level,
+ // resetting this won't lift it from that level.
+ ts[TIME_STAMP_INDEX_BG_RESTRICTED] = 0;
+ // Now need to notify the controller.
}
}
}
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index 004760a302a7..6c183626fdad 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -24,6 +24,7 @@ import static android.app.ActivityManager.RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
import static android.app.ActivityManager.RESTRICTION_LEVEL_BACKGROUND_RESTRICTED;
import static android.app.ActivityManager.RESTRICTION_LEVEL_EXEMPTED;
import static android.app.ActivityManager.RESTRICTION_LEVEL_HIBERNATION;
+import static android.app.ActivityManager.RESTRICTION_LEVEL_MAX;
import static android.app.ActivityManager.RESTRICTION_LEVEL_RESTRICTED_BUCKET;
import static android.app.ActivityManager.RESTRICTION_LEVEL_UNKNOWN;
import static android.app.ActivityManager.UID_OBSERVER_ACTIVE;
@@ -678,7 +679,7 @@ public final class AppRestrictionController {
/**
* Default value to {@link #mBgAbusiveNotificationMinIntervalMs}.
*/
- static final long DEFAULT_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL_MS = ONE_DAY;
+ static final long DEFAULT_BG_ABUSIVE_NOTIFICATION_MINIMAL_INTERVAL_MS = 30 * ONE_DAY;
/**
* Default value to {@link #mBgAbusiveNotificationMinIntervalMs}.
@@ -1152,7 +1153,8 @@ public final class AppRestrictionController {
? RESTRICTION_LEVEL_RESTRICTED_BUCKET
: RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
if (calcTrackers) {
- @RestrictionLevel int l = calcAppRestrictionLevelFromTackers(uid, packageName);
+ @RestrictionLevel int l = calcAppRestrictionLevelFromTackers(uid, packageName,
+ RESTRICTION_LEVEL_MAX);
if (l == RESTRICTION_LEVEL_EXEMPTED) {
return RESTRICTION_LEVEL_EXEMPTED;
}
@@ -1164,7 +1166,8 @@ public final class AppRestrictionController {
uid, 0, packageName).sendToTarget();
}
// Lower the level.
- level = RESTRICTION_LEVEL_RESTRICTED_BUCKET;
+ level = calcAppRestrictionLevelFromTackers(uid, packageName,
+ RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
}
}
break;
@@ -1181,12 +1184,13 @@ public final class AppRestrictionController {
* monitors certain dimensions of the app, the abusive behaviors could be detected in one or
* more of these dimensions, but not necessarily all of them. </p>
*/
- private @RestrictionLevel int calcAppRestrictionLevelFromTackers(int uid, String packageName) {
+ private @RestrictionLevel int calcAppRestrictionLevelFromTackers(int uid, String packageName,
+ @RestrictionLevel int maxLevel) {
@RestrictionLevel int level = RESTRICTION_LEVEL_UNKNOWN;
final boolean isRestrictedBucketEnabled = mConstantsObserver.mRestrictedBucketEnabled;
for (int i = mAppStateTrackers.size() - 1; i >= 0; i--) {
@RestrictionLevel int l = mAppStateTrackers.get(i).getPolicy()
- .getProposedRestrictionLevel(packageName, uid);
+ .getProposedRestrictionLevel(packageName, uid, maxLevel);
if (!isRestrictedBucketEnabled && l == RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
l = RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
}
@@ -1475,17 +1479,15 @@ public final class AppRestrictionController {
} else if (curLevel >= RESTRICTION_LEVEL_RESTRICTED_BUCKET
&& level < RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
// Moved out of the background-restricted state.
- if (curBucket != STANDBY_BUCKET_RARE) {
- synchronized (mSettingsLock) {
- final int index = mActiveUids.indexOfKey(uid, pkgName);
- if (index >= 0) {
- mActiveUids.add(uid, pkgName, null);
- }
+ synchronized (mSettingsLock) {
+ final int index = mActiveUids.indexOfKey(uid, pkgName);
+ if (index >= 0) {
+ mActiveUids.add(uid, pkgName, null);
}
- appStandbyInternal.maybeUnrestrictApp(pkgName, UserHandle.getUserId(uid),
- prevReason & REASON_MAIN_MASK, prevReason & REASON_SUB_MASK,
- reason, subReason);
}
+ appStandbyInternal.maybeUnrestrictApp(pkgName, UserHandle.getUserId(uid),
+ prevReason & REASON_MAIN_MASK, prevReason & REASON_SUB_MASK,
+ reason, subReason);
}
}
diff --git a/services/core/java/com/android/server/am/BaseAppStatePolicy.java b/services/core/java/com/android/server/am/BaseAppStatePolicy.java
index 67318a763907..a55344caea9a 100644
--- a/services/core/java/com/android/server/am/BaseAppStatePolicy.java
+++ b/services/core/java/com/android/server/am/BaseAppStatePolicy.java
@@ -87,9 +87,11 @@ public abstract class BaseAppStatePolicy<T extends BaseAppStateTracker> {
}
/**
- * @return The proposed background restriction policy for the given package/uid.
+ * @return The proposed background restriction policy for the given package/uid,
+ * the returned level should be capped at {@code maxLevel} (exclusive).
*/
- public @RestrictionLevel int getProposedRestrictionLevel(String packageName, int uid) {
+ public @RestrictionLevel int getProposedRestrictionLevel(String packageName, int uid,
+ @RestrictionLevel int maxLevel) {
return RESTRICTION_LEVEL_UNKNOWN;
}
diff --git a/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java b/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
index 2fbca1fa1724..b8aee13ccdd7 100644
--- a/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
+++ b/services/core/java/com/android/server/am/BaseAppStateTimeSlotEventsTracker.java
@@ -18,6 +18,7 @@ package com.android.server.am;
import static android.app.ActivityManager.RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
import static android.app.ActivityManager.RESTRICTION_LEVEL_RESTRICTED_BUCKET;
+import static android.app.ActivityManager.RESTRICTION_LEVEL_UNKNOWN;
import static android.app.usage.UsageStatsManager.REASON_MAIN_FORCED_BY_SYSTEM;
import static android.app.usage.UsageStatsManager.REASON_MAIN_USAGE;
import static android.app.usage.UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_ABUSE;
@@ -295,11 +296,19 @@ abstract class BaseAppStateTimeSlotEventsTracker
}
@Override
- public @RestrictionLevel int getProposedRestrictionLevel(String packageName, int uid) {
+ @RestrictionLevel
+ public int getProposedRestrictionLevel(String packageName, int uid,
+ @RestrictionLevel int maxLevel) {
synchronized (mLock) {
- return mExcessiveEventPkgs.get(packageName, uid) == null
+ final int level = mExcessiveEventPkgs.get(packageName, uid) == null
? RESTRICTION_LEVEL_ADAPTIVE_BUCKET
: RESTRICTION_LEVEL_RESTRICTED_BUCKET;
+ if (maxLevel > RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
+ return level;
+ } else if (maxLevel == RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
+ return RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
+ }
+ return RESTRICTION_LEVEL_UNKNOWN;
}
}
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
index 42a7423725a3..766283b92d91 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerPerUserService.java
@@ -217,9 +217,13 @@ final class AmbientContextManagerPerUserService extends
RemoteCallback detectionResultCallback, RemoteCallback statusCallback) {
Slog.d(TAG, "Requested detection of " + request.getEventTypes());
synchronized (mLock) {
- ensureRemoteServiceInitiated();
- mRemoteService.startDetection(request, callingPackage, detectionResultCallback,
- statusCallback);
+ if (setUpServiceIfNeeded()) {
+ ensureRemoteServiceInitiated();
+ mRemoteService.startDetection(request, callingPackage, detectionResultCallback,
+ statusCallback);
+ } else {
+ Slog.w(TAG, "No valid component found for AmbientContextDetectionService");
+ }
}
}
@@ -371,8 +375,10 @@ final class AmbientContextManagerPerUserService extends
void stopDetection(String packageName) {
Slog.d(TAG, "Stop detection for " + packageName);
synchronized (mLock) {
- ensureRemoteServiceInitiated();
- mRemoteService.stopDetection(packageName);
+ if (mComponentName != null) {
+ ensureRemoteServiceInitiated();
+ mRemoteService.stopDetection(packageName);
+ }
}
}
diff --git a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
index 2cdf7e7c7133..cfca7ec6f568 100644
--- a/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
+++ b/services/core/java/com/android/server/ambientcontext/AmbientContextManagerService.java
@@ -42,6 +42,7 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.FrameworkResourcesServiceNameResolver;
+import com.android.server.pm.KnownPackages;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -117,7 +118,7 @@ public class AmbientContextManagerService extends
public static boolean isDetectionServiceConfigured() {
final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
final String[] packageNames = pmi.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_AMBIENT_CONTEXT_DETECTION, UserHandle.USER_SYSTEM);
+ KnownPackages.PACKAGE_AMBIENT_CONTEXT_DETECTION, UserHandle.USER_SYSTEM);
boolean isServiceConfigured = (packageNames.length != 0);
Slog.i(TAG, "Detection service configured: " + isServiceConfigured);
return isServiceConfigured;
@@ -249,6 +250,8 @@ public class AmbientContextManagerService extends
Objects.requireNonNull(eventTypes);
Objects.requireNonNull(callingPackage);
assertCalledByPackageOwner(callingPackage);
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.ACCESS_AMBIENT_CONTEXT_EVENT, TAG);
mService.onStartConsentActivity(eventTypes, callingPackage);
}
diff --git a/services/core/java/com/android/server/biometrics/BiometricSensor.java b/services/core/java/com/android/server/biometrics/BiometricSensor.java
index 7166783f0b23..937e3f8f8668 100644
--- a/services/core/java/com/android/server/biometrics/BiometricSensor.java
+++ b/services/core/java/com/android/server/biometrics/BiometricSensor.java
@@ -22,10 +22,8 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.IBiometricAuthenticator;
import android.hardware.biometrics.IBiometricSensorReceiver;
-import android.hardware.biometrics.SensorPropertiesInternal;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
@@ -149,7 +147,7 @@ public abstract class BiometricSensor {
* Returns the actual strength, taking any updated strengths into effect. Since more bits
* means lower strength, the resulting strength is never stronger than the OEM's configured
* strength.
- * @return a bitfield, see {@link BiometricManager.Authenticators}
+ * @return a bitfield, see {@link android.hardware.biometrics.BiometricManager.Authenticators}
*/
@Authenticators.Types int getCurrentStrength() {
return oemStrength | mUpdatedStrength;
@@ -169,27 +167,19 @@ public abstract class BiometricSensor {
* @param newStrength
*/
void updateStrength(@Authenticators.Types int newStrength) {
- String log = "updateStrength: Before(" + toString() + ")";
+ String log = "updateStrength: Before(" + this + ")";
mUpdatedStrength = newStrength;
- log += " After(" + toString() + ")";
+ log += " After(" + this + ")";
Slog.d(TAG, log);
}
@Override
public String toString() {
- SensorPropertiesInternal properties = null;
- try {
- properties = impl.getSensorProperties(mContext.getOpPackageName());
- } catch (RemoteException e) {
- Slog.e(TAG, "Remote exception", e);
- }
-
return "ID(" + id + ")"
+ ", oemStrength: " + oemStrength
+ ", updatedStrength: " + mUpdatedStrength
+ ", modality " + modality
+ ", state: " + mSensorState
- + ", cookie: " + mCookie
- + ", props: " + properties;
+ + ", cookie: " + mCookie;
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 82e1efd1b884..c88e3eb6d507 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -446,14 +446,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// PowerManager.BRIGHTNESS_INVALID_FLOAT when there's no temporary adjustment set.
private float mTemporaryAutoBrightnessAdjustment;
- // Whether reduce bright colors (rbc) has been turned on, or a change in strength has been
- // requested. We want to retain the current backlight level when rbc is toggled, since rbc
- // additionally makes the screen appear dimmer using screen colors rather than backlight levels,
- // and therefore we don't actually want to compensate for this by then in/decreasing the
- // backlight when toggling this feature.
- // This should be false during system start up.
- private boolean mPendingRbcOnOrChanged = false;
-
// Animators.
private ObjectAnimator mColorFadeOnAnimator;
private ObjectAnimator mColorFadeOffAnimator;
@@ -572,20 +564,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
@Override
public void onReduceBrightColorsActivationChanged(boolean activated,
boolean userInitiated) {
- applyReduceBrightColorsSplineAdjustment(
- /* rbcStrengthChanged= */ false, activated);
+ applyReduceBrightColorsSplineAdjustment();
}
@Override
public void onReduceBrightColorsStrengthChanged(int strength) {
- applyReduceBrightColorsSplineAdjustment(
- /* rbcStrengthChanged= */ true, /* justActivated= */ false);
+ applyReduceBrightColorsSplineAdjustment();
}
});
if (active) {
- applyReduceBrightColorsSplineAdjustment(
- /* rbcStrengthChanged= */ false, /* justActivated= */ false);
+ applyReduceBrightColorsSplineAdjustment();
}
} else {
mCdsi = null;
@@ -615,15 +604,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
- private void applyReduceBrightColorsSplineAdjustment(
- boolean rbcStrengthChanged, boolean justActivated) {
- final int strengthChanged = rbcStrengthChanged ? 1 : 0;
- final int activated = justActivated ? 1 : 0;
- mHandler.obtainMessage(MSG_UPDATE_RBC, strengthChanged, activated).sendToTarget();
+ private void applyReduceBrightColorsSplineAdjustment() {
+ mHandler.obtainMessage(MSG_UPDATE_RBC).sendToTarget();
sendUpdatePowerState();
}
- private void handleRbcChanged(boolean strengthChanged, boolean justActivated) {
+ private void handleRbcChanged() {
if (mAutomaticBrightnessController == null) {
return;
}
@@ -642,12 +628,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mAutomaticBrightnessController.recalculateSplines(mCdsi.isReduceBrightColorsActivated(),
adjustedNits);
- mPendingRbcOnOrChanged = strengthChanged || justActivated;
- // Reset model if strength changed OR rbc is turned off
- if ((strengthChanged || !justActivated) && mAutomaticBrightnessController != null) {
- mAutomaticBrightnessController.resetShortTermModel();
- }
+ // If rbc is turned on, off or there is a change in strength, we want to reset the short
+ // term model. Since the nits range at which brightness now operates has changed due to
+ // RBC/strength change, any short term model based on the previous range should be
+ // invalidated.
+ mAutomaticBrightnessController.resetShortTermModel();
}
/**
@@ -1019,8 +1005,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private void reloadReduceBrightColours() {
if (mCdsi != null && mCdsi.isReduceBrightColorsActivated()) {
- applyReduceBrightColorsSplineAdjustment(
- /* rbcStrengthChanged= */ false, /* justActivated= */ false);
+ applyReduceBrightColorsSplineAdjustment();
}
}
@@ -2285,23 +2270,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
// We want to return true if the user has set the screen brightness.
- // If they have just turned RBC on (and therefore added that interaction to the curve),
- // or changed the brightness another way, then we should return true.
+ // RBC on, off, and intensity changes will return false.
+ // Slider interactions whilst in RBC will return true, just as when in non-rbc.
private boolean updateUserSetScreenBrightness() {
- final boolean treatAsIfUserChanged = mPendingRbcOnOrChanged;
- if (treatAsIfUserChanged && !Float.isNaN(mCurrentScreenBrightnessSetting)) {
- mLastUserSetScreenBrightness = mCurrentScreenBrightnessSetting;
- }
- mPendingRbcOnOrChanged = false;
-
if ((Float.isNaN(mPendingScreenBrightnessSetting)
|| mPendingScreenBrightnessSetting < 0.0f)) {
- return treatAsIfUserChanged;
+ return false;
}
if (mCurrentScreenBrightnessSetting == mPendingScreenBrightnessSetting) {
mPendingScreenBrightnessSetting = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mTemporaryScreenBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;
- return treatAsIfUserChanged;
+ return false;
}
setCurrentScreenBrightness(mPendingScreenBrightnessSetting);
mLastUserSetScreenBrightness = mPendingScreenBrightnessSetting;
@@ -2691,9 +2670,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
break;
case MSG_UPDATE_RBC:
- final int strengthChanged = msg.arg1;
- final int justActivated = msg.arg2;
- handleRbcChanged(strengthChanged == 1, justActivated == 1);
+ handleRbcChanged();
break;
case MSG_BRIGHTNESS_RAMP_DONE:
diff --git a/services/core/java/com/android/server/display/OWNERS b/services/core/java/com/android/server/display/OWNERS
index 09d96be43a43..8e3460175158 100644
--- a/services/core/java/com/android/server/display/OWNERS
+++ b/services/core/java/com/android/server/display/OWNERS
@@ -3,5 +3,6 @@ dangittik@google.com
hackbod@google.com
ogunwale@google.com
santoscordon@google.com
+flc@google.com
per-file ColorDisplayService.java=christyfranks@google.com
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 6cfaf9cce092..78cffa6f4f79 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -635,7 +635,7 @@ public class LockSettingsService extends ILockSettings.Stub {
* If the account is credential-encrypted, show notification requesting the user to unlock the
* device.
*/
- private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId) {
+ private void maybeShowEncryptionNotificationForUser(@UserIdInt int userId, String reason) {
final UserInfo user = mUserManager.getUserInfo(userId);
if (!user.isManagedProfile()) {
// When the user is locked, we communicate it loud-and-clear
@@ -659,28 +659,35 @@ public class LockSettingsService extends ILockSettings.Stub {
!mUserManager.isQuietModeEnabled(userHandle)) {
// Only show notifications for managed profiles once their parent
// user is unlocked.
- showEncryptionNotificationForProfile(userHandle);
+ showEncryptionNotificationForProfile(userHandle, reason);
}
}
}
- private void showEncryptionNotificationForProfile(UserHandle user) {
+ private void showEncryptionNotificationForProfile(UserHandle user, String reason) {
Resources r = mContext.getResources();
CharSequence title = getEncryptionNotificationTitle();
CharSequence message = getEncryptionNotificationMessage();
CharSequence detail = getEncryptionNotificationDetail();
final KeyguardManager km = (KeyguardManager) mContext.getSystemService(KEYGUARD_SERVICE);
- final Intent unlockIntent = km.createConfirmDeviceCredentialIntent(null, null,
- user.getIdentifier());
+ final Intent unlockIntent =
+ km.createConfirmDeviceCredentialIntent(null, null, user.getIdentifier());
if (unlockIntent == null) {
return;
}
+
+ // Suppress all notifications on non-FBE devices for now
+ if (!StorageManager.isFileEncryptedNativeOrEmulated()) return;
+
unlockIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
PendingIntent intent = PendingIntent.getActivity(mContext, 0, unlockIntent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE_UNAUDITED);
+ Slog.d(TAG, String.format("showing encryption notification, user: %d; reason: %s",
+ user.getIdentifier(), reason));
+
showEncryptionNotification(user, title, message, detail, intent);
}
@@ -704,11 +711,6 @@ public class LockSettingsService extends ILockSettings.Stub {
private void showEncryptionNotification(UserHandle user, CharSequence title,
CharSequence message, CharSequence detail, PendingIntent intent) {
- if (DEBUG) Slog.v(TAG, "showing encryption notification, user: " + user.getIdentifier());
-
- // Suppress all notifications on non-FBE devices for now
- if (!StorageManager.isFileEncryptedNativeOrEmulated()) return;
-
Notification notification =
new Notification.Builder(mContext, SystemNotificationChannels.DEVICE_ADMIN)
.setSmallIcon(com.android.internal.R.drawable.ic_user_secure)
@@ -728,7 +730,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
private void hideEncryptionNotification(UserHandle userHandle) {
- if (DEBUG) Slog.v(TAG, "hide encryption notification, user: " + userHandle.getIdentifier());
+ Slog.d(TAG, "hide encryption notification, user: " + userHandle.getIdentifier());
mNotificationManager.cancelAsUser(null, SystemMessage.NOTE_FBE_ENCRYPTED_NOTIFICATION,
userHandle);
}
@@ -746,7 +748,7 @@ public class LockSettingsService extends ILockSettings.Stub {
}
public void onStartUser(final int userId) {
- maybeShowEncryptionNotificationForUser(userId);
+ maybeShowEncryptionNotificationForUser(userId, "user started");
}
/**
@@ -1497,7 +1499,7 @@ public class LockSettingsService extends ILockSettings.Stub {
if (!alreadyUnlocked) {
final long ident = clearCallingIdentity();
try {
- maybeShowEncryptionNotificationForUser(profile.id);
+ maybeShowEncryptionNotificationForUser(profile.id, "parent unlocked");
} finally {
restoreCallingIdentity(ident);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index a284ada11a49..a04204d90302 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -5030,8 +5030,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
if (oldEffectiveBlockedReasons != newEffectiveBlockedReasons) {
postBlockedReasonsChangedMsg(uid,
- oldEffectiveBlockedReasons,
- newEffectiveBlockedReasons);
+ newEffectiveBlockedReasons,
+ oldEffectiveBlockedReasons);
postUidRulesChangedMsg(uid, uidRules);
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index ee0b3d52eb3d..8ecc607603a1 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -82,6 +82,7 @@ import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import com.android.server.SystemService;
+import com.android.server.pm.KnownPackages;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -1264,7 +1265,7 @@ public final class OverlayManagerService extends SystemService {
@Override
public String getConfigSignaturePackage() {
final String[] pkgs = mPackageManagerInternal.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_OVERLAY_CONFIG_SIGNATURE,
+ KnownPackages.PACKAGE_OVERLAY_CONFIG_SIGNATURE,
UserHandle.USER_SYSTEM);
return (pkgs.length == 0) ? null : pkgs[0];
}
diff --git a/services/core/java/com/android/server/pm/Computer.java b/services/core/java/com/android/server/pm/Computer.java
index 8e853019de90..3e204b6e6e4c 100644
--- a/services/core/java/com/android/server/pm/Computer.java
+++ b/services/core/java/com/android/server/pm/Computer.java
@@ -45,6 +45,7 @@ import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
import android.util.SparseArray;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.pm.parsing.pkg.AndroidPackage;
@@ -571,6 +572,31 @@ public interface Computer extends PackageDataSnapshot {
@NonNull
WatchedArrayMap<String, Integer> getFrozenPackages();
+ /**
+ * Verify that given package is currently frozen.
+ */
+ void checkPackageFrozen(@NonNull String packageName);
+
@Nullable
ComponentName getInstantAppInstallerComponent();
+
+ void dumpPermissions(@NonNull PrintWriter pw, @NonNull String packageName,
+ @NonNull ArraySet<String> permissionNames, @NonNull DumpState dumpState);
+
+ void dumpPackages(PrintWriter pw, @NonNull String packageName,
+ @NonNull ArraySet<String> permissionNames, @NonNull DumpState dumpState,
+ boolean checkin);
+
+ void dumpKeySet(@NonNull PrintWriter pw, @NonNull String packageName,
+ @NonNull DumpState dumpState);
+
+ void dumpSharedUsers(@NonNull PrintWriter pw, @NonNull String packageName,
+ @NonNull ArraySet<String> permissionNames,
+ @NonNull DumpState dumpState, boolean checkin);
+
+ void dumpSharedUsersProto(@NonNull ProtoOutputStream proto);
+
+ void dumpPackagesProto(@NonNull ProtoOutputStream proto);
+
+ void dumpSharedLibrariesProto(@NonNull ProtoOutputStream protoOutputStream);
}
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 4abfd3404295..8432f48e269e 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -117,6 +117,7 @@ import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.TypedXmlSerializer;
import android.util.Xml;
+import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
@@ -322,6 +323,37 @@ public class ComputerEngine implements Computer {
}
return res;
}
+
+ public void dumpPackagesProto(ProtoOutputStream proto) {
+ mSettings.dumpPackagesProto(proto);
+ }
+
+ public void dumpPermissions(PrintWriter pw, String packageName,
+ ArraySet<String> permissionNames, DumpState dumpState) {
+ mSettings.dumpPermissions(pw, packageName, permissionNames, dumpState);
+ }
+
+ public void dumpPackages(PrintWriter pw, String packageName,
+ ArraySet<String> permissionNames, DumpState dumpState, boolean checkin) {
+ mSettings.dumpPackagesLPr(pw, packageName, permissionNames, dumpState, checkin);
+ }
+
+ public void dumpKeySet(PrintWriter pw, String packageName, DumpState dumpState) {
+ mSettings.getKeySetManagerService().dumpLPr(pw, packageName, dumpState);
+ }
+
+ public void dumpSharedUsers(PrintWriter pw, String packageName,
+ ArraySet<String> permissionNames, DumpState dumpState, boolean checkin) {
+ mSettings.dumpSharedUsersLPr(pw, packageName, permissionNames, dumpState, checkin);
+ }
+
+ public void dumpReadMessages(PrintWriter pw, DumpState dumpState) {
+ mSettings.dumpReadMessages(pw, dumpState);
+ }
+
+ public void dumpSharedUsersProto(ProtoOutputStream proto) {
+ mSettings.dumpSharedUsersProto(proto);
+ }
}
private static final Comparator<ProviderInfo> sProviderInitOrderSorter = (p1, p2) -> {
@@ -3211,6 +3243,34 @@ public class ComputerEngine implements Computer {
}
break;
}
+
+ case DumpState.DUMP_MESSAGES: {
+ mSettings.dumpReadMessages(pw, dumpState);
+ break;
+ }
+
+ case DumpState.DUMP_FROZEN: {
+ // XXX should handle packageName != null by dumping only install data that
+ // the given package is involved with.
+ if (dumpState.onTitlePrinted()) {
+ pw.println();
+ }
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
+ ipw.println();
+ ipw.println("Frozen packages:");
+ ipw.increaseIndent();
+ if (mFrozenPackages.size() == 0) {
+ ipw.println("(none)");
+ } else {
+ for (int i = 0; i < mFrozenPackages.size(); i++) {
+ ipw.print("package=");
+ ipw.print(mFrozenPackages.keyAt(i));
+ ipw.print(", refCounts=");
+ ipw.println(mFrozenPackages.valueAt(i));
+ }
+ }
+ ipw.decreaseIndent();
+ }
} // switch
}
@@ -5698,10 +5758,58 @@ public class ComputerEngine implements Computer {
return mFrozenPackages;
}
+ @Override
+ public void checkPackageFrozen(@NonNull String packageName) {
+ if (!mFrozenPackages.containsKey(packageName)) {
+ Slog.wtf(TAG, "Expected " + packageName + " to be frozen!", new Throwable());
+ }
+ }
+
@Nullable
@Override
public ComponentName getInstantAppInstallerComponent() {
return mLocalInstantAppInstallerActivity == null
? null : mLocalInstantAppInstallerActivity.getComponentName();
}
+
+ @Override
+ public void dumpPermissions(@NonNull PrintWriter pw, @NonNull String packageName,
+ @NonNull ArraySet<String> permissionNames, @NonNull DumpState dumpState) {
+ mSettings.dumpPermissions(pw, packageName, permissionNames, dumpState);
+ }
+
+ @Override
+ public void dumpPackages(@NonNull PrintWriter pw, @NonNull String packageName,
+ @NonNull ArraySet<String> permissionNames, @NonNull DumpState dumpState,
+ boolean checkin) {
+ mSettings.dumpPackages(pw, packageName, permissionNames, dumpState, checkin);
+ }
+
+ @Override
+ public void dumpKeySet(@NonNull PrintWriter pw, @NonNull String packageName,
+ @NonNull DumpState dumpState) {
+ mSettings.dumpKeySet(pw, packageName, dumpState);
+ }
+
+ @Override
+ public void dumpSharedUsers(@NonNull PrintWriter pw, @NonNull String packageName,
+ @NonNull ArraySet<String> permissionNames, @NonNull DumpState dumpState,
+ boolean checkin) {
+ mSettings.dumpSharedUsers(pw, packageName, permissionNames, dumpState, checkin);
+ }
+
+ @Override
+ public void dumpSharedUsersProto(@NonNull ProtoOutputStream proto) {
+ mSettings.dumpSharedUsersProto(proto);
+ }
+
+ @Override
+ public void dumpPackagesProto(@NonNull ProtoOutputStream proto) {
+ mSettings.dumpPackagesProto(proto);
+ }
+
+ @Override
+ public void dumpSharedLibrariesProto(@NonNull ProtoOutputStream proto) {
+ mSharedLibraries.dumpProto(proto);
+ }
}
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index dc4dd12b3a18..7dae22a44cc5 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -167,6 +167,7 @@ final class DeletePackageHelper {
if (userInfo == null || !userInfo.isAdmin()) {
Slog.w(TAG, "Not removing package " + packageName
+ " as only admin user may downgrade system apps");
+ EventLog.writeEvent(0x534e4554, "170646036", -1, packageName);
return PackageManager.DELETE_FAILED_USER_RESTRICTED;
}
}
diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java
index f83ef5aea23a..276644036def 100644
--- a/services/core/java/com/android/server/pm/DumpHelper.java
+++ b/services/core/java/com/android/server/pm/DumpHelper.java
@@ -17,45 +17,76 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.MATCH_DEBUG_TRIAGED_MISSING;
-import static android.content.pm.PackageManagerInternal.LAST_KNOWN_PACKAGE;
+import static com.android.server.pm.KnownPackages.LAST_KNOWN_PACKAGE;
import static com.android.server.pm.PackageManagerServiceUtils.dumpCriticalInfo;
+import android.annotation.NonNull;
import android.content.ComponentName;
import android.content.pm.FeatureInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
import android.os.Binder;
import android.os.UserHandle;
import android.os.incremental.PerUidReadTimeouts;
import android.service.pm.PackageServiceDumpProto;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.pm.permission.PermissionManagerServiceInternal;
+import com.android.server.pm.resolution.ComponentResolverApi;
+import com.android.server.pm.verify.domain.DomainVerificationManagerInternal;
import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy;
import dalvik.annotation.optimization.NeverCompile;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.function.BiConsumer;
/**
* Dumps PackageManagerService internal states.
*/
final class DumpHelper {
- final PackageManagerService mPm;
-
- DumpHelper(PackageManagerService pm) {
- mPm = pm;
+ private final PermissionManagerServiceInternal mPermissionManager;
+ private final ApexManager mApexManager;
+ private final StorageEventHelper mStorageEventHelper;
+ private final DomainVerificationManagerInternal mDomainVerificationManager;
+ private final PackageInstallerService mInstallerService;
+ private final String mRequiredVerifierPackage;
+ private final KnownPackages mKnownPackages;
+ private final ChangedPackagesTracker mChangedPackagesTracker;
+ private final ArrayMap<String, FeatureInfo> mAvailableFeatures;
+ private final ArraySet<String> mProtectedBroadcasts;
+ private final PerUidReadTimeouts[] mPerUidReadTimeouts;
+
+ DumpHelper(
+ PermissionManagerServiceInternal permissionManager, ApexManager apexManager,
+ StorageEventHelper storageEventHelper,
+ DomainVerificationManagerInternal domainVerificationManager,
+ PackageInstallerService installerService, String requiredVerifierPackage,
+ KnownPackages knownPackages,
+ ChangedPackagesTracker changedPackagesTracker,
+ ArrayMap<String, FeatureInfo> availableFeatures,
+ ArraySet<String> protectedBroadcasts,
+ PerUidReadTimeouts[] perUidReadTimeouts) {
+ mPermissionManager = permissionManager;
+ mApexManager = apexManager;
+ mStorageEventHelper = storageEventHelper;
+ mDomainVerificationManager = domainVerificationManager;
+ mInstallerService = installerService;
+ mRequiredVerifierPackage = requiredVerifierPackage;
+ mKnownPackages = knownPackages;
+ mChangedPackagesTracker = changedPackagesTracker;
+ mAvailableFeatures = availableFeatures;
+ mProtectedBroadcasts = protectedBroadcasts;
+ mPerUidReadTimeouts = perUidReadTimeouts;
}
@NeverCompile // Avoid size overhead of debugging code.
- public void doDump(FileDescriptor fd, PrintWriter pw, String[] args) {
- final Computer snapshot = mPm.snapshotComputer();
+ public void doDump(Computer snapshot, FileDescriptor fd, PrintWriter pw, String[] args) {
DumpState dumpState = new DumpState();
ArraySet<String> permissionNames = null;
@@ -79,7 +110,7 @@ final class DumpHelper {
} else if ("-f".equals(opt)) {
dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS);
} else if ("--proto".equals(opt)) {
- dumpProto(fd);
+ dumpProto(snapshot, fd);
return;
} else {
pw.println("Unknown argument: " + opt + "; use -h for help");
@@ -122,9 +153,10 @@ final class DumpHelper {
}
// Normalize package name to handle renamed packages and static libs
- pkg = snapshot.resolveInternalPackageName(pkg, PackageManager.VERSION_CODE_HIGHEST);
+ pkg = snapshot.resolveInternalPackageName(pkg,
+ PackageManager.VERSION_CODE_HIGHEST);
- pw.println(mPm.checkPermission(perm, pkg, user));
+ pw.println(mPermissionManager.checkPermission(perm, pkg, user));
return;
} else if ("l".equals(cmd) || "libraries".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_LIBS);
@@ -230,12 +262,6 @@ final class DumpHelper {
}
} else if ("protected-broadcasts".equals(cmd)) {
dumpState.setDump(DumpState.DUMP_PROTECTED_BROADCASTS);
- } else if ("write".equals(cmd)) {
- synchronized (mPm.mLock) {
- mPm.writeSettingsLPrTEMP();
- pw.println("Settings written.");
- return;
- }
}
}
@@ -245,7 +271,7 @@ final class DumpHelper {
// Return if the package doesn't exist.
if (packageName != null
&& snapshot.getPackageStateInternal(packageName) == null
- && !mPm.mApexManager.isApexPackage(packageName)) {
+ && !mApexManager.isApexPackage(packageName)) {
pw.println("Unable to find package: " + packageName);
return;
}
@@ -271,11 +297,11 @@ final class DumpHelper {
ipw.println("Known Packages:");
ipw.increaseIndent();
for (int i = 0; i <= LAST_KNOWN_PACKAGE; i++) {
- final String knownPackage = PackageManagerInternal.knownPackageToString(i);
+ final String knownPackage = KnownPackages.knownPackageToString(i);
ipw.print(knownPackage);
ipw.println(":");
- final String[] pkgNames = mPm.getKnownPackageNamesInternal(snapshot, i,
- UserHandle.USER_SYSTEM);
+ final String[] pkgNames = mKnownPackages.getKnownPackageNames(snapshot,
+ i, UserHandle.USER_SYSTEM);
ipw.increaseIndent();
if (ArrayUtils.isEmpty(pkgNames)) {
ipw.println("none");
@@ -291,7 +317,7 @@ final class DumpHelper {
if (dumpState.isDumping(DumpState.DUMP_VERIFIERS)
&& packageName == null) {
- final String requiredVerifierPackage = mPm.mRequiredVerifierPackage;
+ final String requiredVerifierPackage = mRequiredVerifierPackage;
if (!checkin) {
if (dumpState.onTitlePrinted()) {
pw.println();
@@ -304,7 +330,8 @@ final class DumpHelper {
MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
pw.println(")");
} else if (requiredVerifierPackage != null) {
- pw.print("vrfy,"); pw.print(requiredVerifierPackage);
+ pw.print("vrfy,");
+ pw.print(requiredVerifierPackage);
pw.print(",");
pw.println(snapshot.getPackageUid(requiredVerifierPackage,
MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
@@ -313,7 +340,7 @@ final class DumpHelper {
if (dumpState.isDumping(DumpState.DUMP_DOMAIN_VERIFIER)
&& packageName == null) {
- final DomainVerificationProxy proxy = mPm.mDomainVerificationManager.getProxy();
+ final DomainVerificationProxy proxy = mDomainVerificationManager.getProxy();
final ComponentName verifierComponent = proxy.getComponentName();
if (verifierComponent != null) {
String verifierPackageName = verifierComponent.getPackageName();
@@ -329,7 +356,8 @@ final class DumpHelper {
MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
pw.println(")");
} else if (verifierPackageName != null) {
- pw.print("dv,"); pw.print(verifierPackageName);
+ pw.print("dv,");
+ pw.print(verifierPackageName);
pw.print(",");
pw.println(snapshot.getPackageUid(verifierPackageName,
MATCH_DEBUG_TRIAGED_MISSING, UserHandle.USER_SYSTEM));
@@ -354,76 +382,75 @@ final class DumpHelper {
pw.println("Features:");
}
- synchronized (mPm.mAvailableFeatures) {
- for (FeatureInfo feat : mPm.mAvailableFeatures.values()) {
- if (!checkin) {
- pw.print(" ");
- pw.print(feat.name);
- if (feat.version > 0) {
- pw.print(" version=");
- pw.print(feat.version);
- }
- pw.println();
- } else {
- pw.print("feat,");
- pw.print(feat.name);
- pw.print(",");
- pw.println(feat.version);
+ for (FeatureInfo feat : mAvailableFeatures.values()) {
+ if (!checkin) {
+ pw.print(" ");
+ pw.print(feat.name);
+ if (feat.version > 0) {
+ pw.print(" version=");
+ pw.print(feat.version);
}
+ pw.println();
+ } else {
+ pw.print("feat,");
+ pw.print(feat.name);
+ pw.print(",");
+ pw.println(feat.version);
}
}
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_ACTIVITY_RESOLVERS)) {
- mPm.mComponentResolver.dumpActivityResolvers(pw, dumpState, packageName);
+ final ComponentResolverApi componentResolver = snapshot.getComponentResolver();
+ if (!checkin
+ && dumpState.isDumping(DumpState.DUMP_ACTIVITY_RESOLVERS)) {
+ componentResolver.dumpActivityResolvers(pw, dumpState, packageName);
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_RECEIVER_RESOLVERS)) {
- mPm.mComponentResolver.dumpReceiverResolvers(pw, dumpState, packageName);
+ if (!checkin
+ && dumpState.isDumping(DumpState.DUMP_RECEIVER_RESOLVERS)) {
+ componentResolver.dumpReceiverResolvers(pw, dumpState, packageName);
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_RESOLVERS)) {
- mPm.mComponentResolver.dumpServiceResolvers(pw, dumpState, packageName);
+ if (!checkin
+ && dumpState.isDumping(DumpState.DUMP_SERVICE_RESOLVERS)) {
+ componentResolver.dumpServiceResolvers(pw, dumpState, packageName);
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_CONTENT_RESOLVERS)) {
- mPm.mComponentResolver.dumpProviderResolvers(pw, dumpState, packageName);
+ if (!checkin
+ && dumpState.isDumping(DumpState.DUMP_CONTENT_RESOLVERS)) {
+ componentResolver.dumpProviderResolvers(pw, dumpState, packageName);
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
+ if (!checkin
+ && dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
snapshot.dump(DumpState.DUMP_PREFERRED, fd, pw, dumpState);
}
if (!checkin
- && dumpState.isDumping(DumpState.DUMP_PREFERRED_XML)
- && packageName == null) {
+ && dumpState.isDumping(DumpState.DUMP_PREFERRED_XML) && packageName == null) {
snapshot.dump(DumpState.DUMP_PREFERRED_XML, fd, pw, dumpState);
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)) {
+ if (!checkin
+ && dumpState.isDumping(DumpState.DUMP_DOMAIN_PREFERRED)) {
snapshot.dump(DumpState.DUMP_DOMAIN_PREFERRED, fd, pw, dumpState);
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
- mPm.mSettings.dumpPermissions(pw, packageName, permissionNames, dumpState);
+ if (!checkin
+ && dumpState.isDumping(DumpState.DUMP_PERMISSIONS)) {
+ snapshot.dumpPermissions(pw, packageName, permissionNames, dumpState);
}
- if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
- mPm.mComponentResolver.dumpContentProviders(snapshot, pw, dumpState,
+ if (!checkin
+ && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
+ componentResolver.dumpContentProviders(snapshot, pw, dumpState,
packageName);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
- synchronized (mPm.mLock) {
- mPm.mSettings.getKeySetManagerService().dumpLPr(pw, packageName, dumpState);
- }
+ snapshot.dumpKeySet(pw, packageName, dumpState);
}
if (dumpState.isDumping(DumpState.DUMP_PACKAGES)) {
- // This cannot be moved to ComputerEngine since some variables of the collections
- // in PackageUserState such as suspendParams, disabledComponents and enabledComponents
- // do not have a copy.
- synchronized (mPm.mLock) {
- mPm.mSettings.dumpPackagesLPr(pw, packageName, permissionNames, dumpState, checkin);
- }
+ snapshot.dumpPackages(pw, packageName, permissionNames, dumpState, checkin);
}
if (!checkin
@@ -432,12 +459,8 @@ final class DumpHelper {
}
if (dumpState.isDumping(DumpState.DUMP_SHARED_USERS)) {
- // This cannot be moved to ComputerEngine since the set of packages in the
- // SharedUserSetting do not have a copy.
- synchronized (mPm.mLock) {
- mPm.mSettings.dumpSharedUsersLPr(pw, packageName, permissionNames, dumpState,
- checkin);
- }
+ snapshot.dumpSharedUsers(pw, packageName, permissionNames, dumpState,
+ checkin);
}
if (!checkin
@@ -447,15 +470,19 @@ final class DumpHelper {
pw.println();
}
pw.println("Package Changes:");
- mPm.mChangedPackagesTracker.iterateAll((sequenceNumber, values) -> {
- pw.print(" Sequence number="); pw.println(sequenceNumber);
+ mChangedPackagesTracker.iterateAll((sequenceNumber, values) -> {
+ pw.print(" Sequence number=");
+ pw.println(sequenceNumber);
final int numChangedPackages = values.size();
for (int i = 0; i < numChangedPackages; i++) {
final SparseArray<String> changes = values.valueAt(i);
- pw.print(" User "); pw.print(values.keyAt(i)); pw.println(":");
+ pw.print(" User ");
+ pw.print(values.keyAt(i));
+ pw.println(":");
final int numChanges = changes.size();
if (numChanges == 0) {
- pw.print(" "); pw.println("No packages changed");
+ pw.print(" ");
+ pw.println("No packages changed");
} else {
for (int j = 0; j < numChanges; j++) {
final String pkgName = changes.valueAt(j);
@@ -474,56 +501,19 @@ final class DumpHelper {
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_FROZEN)
&& packageName == null) {
- // XXX should handle packageName != null by dumping only install data that
- // the given package is involved with.
- if (dumpState.onTitlePrinted()) {
- pw.println();
- }
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
- ipw.println();
- ipw.println("Frozen packages:");
- ipw.increaseIndent();
- synchronized (mPm.mLock) {
- if (mPm.mFrozenPackages.size() == 0) {
- ipw.println("(none)");
- } else {
- for (int i = 0; i < mPm.mFrozenPackages.size(); i++) {
- ipw.print("package=");
- ipw.print(mPm.mFrozenPackages.keyAt(i));
- ipw.print(", refCounts=");
- ipw.println(mPm.mFrozenPackages.valueAt(i));
- }
- }
- }
- ipw.decreaseIndent();
+ snapshot.dump(DumpState.DUMP_FROZEN, fd, pw, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_VOLUMES)
&& packageName == null) {
- if (dumpState.onTitlePrinted()) {
- pw.println();
- }
- final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
- ipw.println();
- ipw.println("Loaded volumes:");
- ipw.increaseIndent();
- synchronized (mPm.mLoadedVolumes) {
- if (mPm.mLoadedVolumes.size() == 0) {
- ipw.println("(none)");
- } else {
- for (int i = 0; i < mPm.mLoadedVolumes.size(); i++) {
- ipw.println(mPm.mLoadedVolumes.valueAt(i));
- }
- }
- }
- ipw.decreaseIndent();
+ mStorageEventHelper.dumpLoadedVolumes(pw, dumpState);
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_SERVICE_PERMISSIONS)
&& packageName == null) {
- mPm.mComponentResolver.dumpServicePermissions(pw, dumpState);
+ componentResolver.dumpServicePermissions(pw, dumpState);
}
if (!checkin
@@ -542,7 +532,7 @@ final class DumpHelper {
if (dumpState.onTitlePrinted()) {
pw.println();
}
- mPm.mSettings.dumpReadMessages(pw, dumpState);
+ snapshot.dump(DumpState.DUMP_MESSAGES, fd, pw, dumpState);
pw.println();
pw.println("Package warning messages:");
dumpCriticalInfo(pw, null);
@@ -560,13 +550,13 @@ final class DumpHelper {
if (dumpState.onTitlePrinted()) {
pw.println();
}
- mPm.mInstallerService.dump(new IndentingPrintWriter(pw, " ", 120));
+ mInstallerService.dump(new IndentingPrintWriter(pw, " ", 120));
}
if (!checkin
&& dumpState.isDumping(DumpState.DUMP_APEX)
- && (packageName == null || mPm.mApexManager.isApexPackage(packageName))) {
- mPm.mApexManager.dump(pw, packageName);
+ && (packageName == null || mApexManager.isApexPackage(packageName))) {
+ mApexManager.dump(pw, packageName);
}
if (!checkin
@@ -580,9 +570,8 @@ final class DumpHelper {
pw.println(" Known digesters list flag: "
+ PackageManagerService.getKnownDigestersList());
- PerUidReadTimeouts[] items = mPm.getPerUidReadTimeouts(snapshot);
- pw.println(" Timeouts (" + items.length + "):");
- for (PerUidReadTimeouts item : items) {
+ pw.println(" Timeouts (" + mPerUidReadTimeouts.length + "):");
+ for (PerUidReadTimeouts item : mPerUidReadTimeouts) {
pw.print(" (");
pw.print("uid=" + item.uid + ", ");
pw.print("minTimeUs=" + item.minTimeUs + ", ");
@@ -598,8 +587,6 @@ final class DumpHelper {
if (dumpState.onTitlePrinted()) {
pw.println();
}
- pw.println("Snapshot statistics");
- mPm.dumpSnapshotStats(pw, dumpState.isBrief());
}
if (!checkin
@@ -609,11 +596,9 @@ final class DumpHelper {
pw.println();
}
pw.println("Protected broadcast actions:");
- synchronized (mPm.mProtectedBroadcasts) {
- for (int i = 0; i < mPm.mProtectedBroadcasts.size(); i++) {
- pw.print(" ");
- pw.println(mPm.mProtectedBroadcasts.valueAt(i));
- }
+ for (int i = 0; i < mProtectedBroadcasts.size(); i++) {
+ pw.print(" ");
+ pw.println(mProtectedBroadcasts.valueAt(i));
}
}
@@ -658,55 +643,50 @@ final class DumpHelper {
pw.println(" <package.name>: info about given package");
}
- private void dumpProto(FileDescriptor fd) {
+ private void dumpProto(Computer snapshot, FileDescriptor fd) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
- synchronized (mPm.mLock) {
- final Computer snapshot = mPm.snapshotComputer();
- final long requiredVerifierPackageToken =
- proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE);
- proto.write(PackageServiceDumpProto.PackageShortProto.NAME,
- mPm.mRequiredVerifierPackage);
+ final long requiredVerifierPackageToken =
+ proto.start(PackageServiceDumpProto.REQUIRED_VERIFIER_PACKAGE);
+ proto.write(PackageServiceDumpProto.PackageShortProto.NAME,
+ mRequiredVerifierPackage);
+ proto.write(
+ PackageServiceDumpProto.PackageShortProto.UID,
+ snapshot.getPackageUid(
+ mRequiredVerifierPackage,
+ MATCH_DEBUG_TRIAGED_MISSING,
+ UserHandle.USER_SYSTEM));
+ proto.end(requiredVerifierPackageToken);
+
+ DomainVerificationProxy proxy = mDomainVerificationManager.getProxy();
+ ComponentName verifierComponent = proxy.getComponentName();
+ if (verifierComponent != null) {
+ String verifierPackageName = verifierComponent.getPackageName();
+ final long verifierPackageToken =
+ proto.start(PackageServiceDumpProto.VERIFIER_PACKAGE);
+ proto.write(PackageServiceDumpProto.PackageShortProto.NAME, verifierPackageName);
proto.write(
PackageServiceDumpProto.PackageShortProto.UID,
snapshot.getPackageUid(
- mPm.mRequiredVerifierPackage,
+ verifierPackageName,
MATCH_DEBUG_TRIAGED_MISSING,
UserHandle.USER_SYSTEM));
- proto.end(requiredVerifierPackageToken);
-
- DomainVerificationProxy proxy = mPm.mDomainVerificationManager.getProxy();
- ComponentName verifierComponent = proxy.getComponentName();
- if (verifierComponent != null) {
- String verifierPackageName = verifierComponent.getPackageName();
- final long verifierPackageToken =
- proto.start(PackageServiceDumpProto.VERIFIER_PACKAGE);
- proto.write(PackageServiceDumpProto.PackageShortProto.NAME, verifierPackageName);
- proto.write(
- PackageServiceDumpProto.PackageShortProto.UID,
- snapshot.getPackageUid(
- verifierPackageName,
- MATCH_DEBUG_TRIAGED_MISSING,
- UserHandle.USER_SYSTEM));
- proto.end(verifierPackageToken);
- }
-
- mPm.mInjector.getSharedLibrariesImpl().dumpProto(proto);
- dumpFeaturesProto(proto);
- mPm.mSettings.dumpPackagesProto(proto);
- mPm.mSettings.dumpSharedUsersProto(proto);
- dumpCriticalInfo(proto);
+ proto.end(verifierPackageToken);
}
+
+ snapshot.dumpSharedLibrariesProto(proto);
+ dumpAvailableFeaturesProto(proto);
+ snapshot.dumpPackagesProto(proto);
+ snapshot.dumpSharedUsersProto(proto);
+ dumpCriticalInfo(proto);
proto.flush();
}
- private void dumpFeaturesProto(ProtoOutputStream proto) {
- synchronized (mPm.mAvailableFeatures) {
- final int count = mPm.mAvailableFeatures.size();
- for (int i = 0; i < count; i++) {
- mPm.mAvailableFeatures.valueAt(i).dumpDebug(proto,
- PackageServiceDumpProto.FEATURES);
- }
+
+ private void dumpAvailableFeaturesProto(@NonNull ProtoOutputStream proto) {
+ final int count = mAvailableFeatures.size();
+ for (int i = 0; i < count; i++) {
+ mAvailableFeatures.valueAt(i).dumpDebug(proto, PackageServiceDumpProto.FEATURES);
}
}
}
diff --git a/services/core/java/com/android/server/pm/IPackageManagerBase.java b/services/core/java/com/android/server/pm/IPackageManagerBase.java
index e1aee6d747f4..ba7309f0283d 100644
--- a/services/core/java/com/android/server/pm/IPackageManagerBase.java
+++ b/services/core/java/com/android/server/pm/IPackageManagerBase.java
@@ -803,7 +803,7 @@ public abstract class IPackageManagerBase extends IPackageManager.Stub {
public final String getSystemCaptionsServicePackageName() {
return mService.ensureSystemPackageName(snapshot(),
mService.getPackageFromComponentString(
- R.string.config_defaultSystemCaptionsService));
+ R.string.config_defaultSystemCaptionsManagerService));
}
@Nullable
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 870a11ac2d61..77d37dc377a2 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -427,7 +427,7 @@ final class InstallPackageHelper {
} else {
// We're doing major surgery on this package, so it better be frozen
// right now to keep it from launching
- mPm.checkPackageFrozen(pkgName);
+ mPm.snapshotComputer().checkPackageFrozen(pkgName);
}
final boolean isReplace =
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 5fadd00b77ad..2a66e026438a 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -692,6 +692,20 @@ public class Installer extends SystemService {
}
}
+ /**
+ * Deletes the reference profile with the given name of the given package.
+ * @throws InstallerException if the deletion fails.
+ */
+ public void deleteReferenceProfile(String packageName, String profileName)
+ throws InstallerException {
+ if (!checkBeforeRemote()) return;
+ try {
+ mInstalld.deleteReferenceProfile(packageName, profileName);
+ } catch (Exception e) {
+ throw InstallerException.from(e);
+ }
+ }
+
public void createUserData(String uuid, int userId, int userSerial, int flags)
throws InstallerException {
if (!checkBeforeRemote()) return;
diff --git a/services/core/java/com/android/server/pm/IntentResolverInterceptor.java b/services/core/java/com/android/server/pm/IntentResolverInterceptor.java
index 5597c9af7362..603badb276b2 100644
--- a/services/core/java/com/android/server/pm/IntentResolverInterceptor.java
+++ b/services/core/java/com/android/server/pm/IntentResolverInterceptor.java
@@ -81,7 +81,7 @@ public final class IntentResolverInterceptor {
private void updateUseDelegateChooser() {
mUseDelegateChooser = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.USE_DELEGATE_CHOOSER,
+ SystemUiDeviceConfigFlags.USE_UNBUNDLED_SHARESHEET,
false);
}
diff --git a/services/core/java/com/android/server/pm/KnownPackages.java b/services/core/java/com/android/server/pm/KnownPackages.java
new file mode 100644
index 000000000000..04376b448e32
--- /dev/null
+++ b/services/core/java/com/android/server/pm/KnownPackages.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.text.TextUtils;
+
+import com.android.internal.util.ArrayUtils;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Helps {@link PackageManagerService} keep track of the names of special packages like SetupWizard.
+ */
+public final class KnownPackages {
+ @IntDef(prefix = "PACKAGE_", value = {
+ PACKAGE_SYSTEM,
+ PACKAGE_SETUP_WIZARD,
+ PACKAGE_INSTALLER,
+ PACKAGE_UNINSTALLER,
+ PACKAGE_VERIFIER,
+ PACKAGE_BROWSER,
+ PACKAGE_SYSTEM_TEXT_CLASSIFIER,
+ PACKAGE_PERMISSION_CONTROLLER,
+ PACKAGE_CONFIGURATOR,
+ PACKAGE_INCIDENT_REPORT_APPROVER,
+ PACKAGE_APP_PREDICTOR,
+ PACKAGE_OVERLAY_CONFIG_SIGNATURE,
+ PACKAGE_WIFI,
+ PACKAGE_COMPANION,
+ PACKAGE_RETAIL_DEMO,
+ PACKAGE_RECENTS,
+ PACKAGE_AMBIENT_CONTEXT_DETECTION,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface KnownPackage {
+ }
+
+ public static final int PACKAGE_SYSTEM = 0;
+ public static final int PACKAGE_SETUP_WIZARD = 1;
+ public static final int PACKAGE_INSTALLER = 2;
+ public static final int PACKAGE_UNINSTALLER = 3;
+ public static final int PACKAGE_VERIFIER = 4;
+ public static final int PACKAGE_BROWSER = 5;
+ public static final int PACKAGE_SYSTEM_TEXT_CLASSIFIER = 6;
+ public static final int PACKAGE_PERMISSION_CONTROLLER = 7;
+ public static final int PACKAGE_WELLBEING = 8;
+ public static final int PACKAGE_DOCUMENTER = 9;
+ public static final int PACKAGE_CONFIGURATOR = 10;
+ public static final int PACKAGE_INCIDENT_REPORT_APPROVER = 11;
+ public static final int PACKAGE_APP_PREDICTOR = 12;
+ public static final int PACKAGE_OVERLAY_CONFIG_SIGNATURE = 13;
+ public static final int PACKAGE_WIFI = 14;
+ public static final int PACKAGE_COMPANION = 15;
+ public static final int PACKAGE_RETAIL_DEMO = 16;
+ public static final int PACKAGE_RECENTS = 17;
+ public static final int PACKAGE_AMBIENT_CONTEXT_DETECTION = 18;
+ // Integer value of the last known package ID. Increases as new ID is added to KnownPackage.
+ // Please note the numbers should be continuous.
+ public static final int LAST_KNOWN_PACKAGE = PACKAGE_AMBIENT_CONTEXT_DETECTION;
+
+ private final DefaultAppProvider mDefaultAppProvider;
+ private final String mRequiredInstallerPackage;
+ private final String mRequiredUninstallerPackage;
+ private final String mSetupWizardPackage;
+ private final String mRequiredVerifierPackage;
+ private final String mDefaultTextClassifierPackage;
+ private final String mSystemTextClassifierPackageName;
+ private final String mRequiredPermissionControllerPackage;
+ private final String mConfiguratorPackage;
+ private final String mIncidentReportApproverPackage;
+ private final String mAmbientContextDetectionPackage;
+ private final String mAppPredictionServicePackage;
+ private final String mCompanionPackage;
+ private final String mRetailDemoPackage;
+ private final String mOverlayConfigSignaturePackage;
+ private final String mRecentsPackage;
+
+ KnownPackages(DefaultAppProvider defaultAppProvider, String requiredInstallerPackage,
+ String requiredUninstallerPackage, String setupWizardPackage,
+ String requiredVerifierPackage, String defaultTextClassifierPackage,
+ String systemTextClassifierPackageName, String requiredPermissionControllerPackage,
+ String configuratorPackage, String incidentReportApproverPackage,
+ String ambientContextDetectionPackage, String appPredictionServicePackage,
+ String companionPackageName, String retailDemoPackage,
+ String overlayConfigSignaturePackage, String recentsPackage) {
+ mDefaultAppProvider = defaultAppProvider;
+ mRequiredInstallerPackage = requiredInstallerPackage;
+ mRequiredUninstallerPackage = requiredUninstallerPackage;
+ mSetupWizardPackage = setupWizardPackage;
+ mRequiredVerifierPackage = requiredVerifierPackage;
+ mDefaultTextClassifierPackage = defaultTextClassifierPackage;
+ mSystemTextClassifierPackageName = systemTextClassifierPackageName;
+ mRequiredPermissionControllerPackage = requiredPermissionControllerPackage;
+ mConfiguratorPackage = configuratorPackage;
+ mIncidentReportApproverPackage = incidentReportApproverPackage;
+ mAmbientContextDetectionPackage = ambientContextDetectionPackage;
+ mAppPredictionServicePackage = appPredictionServicePackage;
+ mCompanionPackage = companionPackageName;
+ mRetailDemoPackage = retailDemoPackage;
+ mOverlayConfigSignaturePackage = overlayConfigSignaturePackage;
+ mRecentsPackage = recentsPackage;
+ }
+
+ /**
+ * Returns the string representation of a known package. For example,
+ * {@link #PACKAGE_SETUP_WIZARD} is represented by the string Setup Wizard.
+ *
+ * @param knownPackage The known package.
+ * @return The string representation.
+ */
+ static @NonNull String knownPackageToString(@KnownPackage int knownPackage) {
+ switch (knownPackage) {
+ case PACKAGE_SYSTEM:
+ return "System";
+ case PACKAGE_SETUP_WIZARD:
+ return "Setup Wizard";
+ case PACKAGE_INSTALLER:
+ return "Installer";
+ case PACKAGE_UNINSTALLER:
+ return "Uninstaller";
+ case PACKAGE_VERIFIER:
+ return "Verifier";
+ case PACKAGE_BROWSER:
+ return "Browser";
+ case PACKAGE_SYSTEM_TEXT_CLASSIFIER:
+ return "System Text Classifier";
+ case PACKAGE_PERMISSION_CONTROLLER:
+ return "Permission Controller";
+ case PACKAGE_WELLBEING:
+ return "Wellbeing";
+ case PACKAGE_DOCUMENTER:
+ return "Documenter";
+ case PACKAGE_CONFIGURATOR:
+ return "Configurator";
+ case PACKAGE_INCIDENT_REPORT_APPROVER:
+ return "Incident Report Approver";
+ case PACKAGE_APP_PREDICTOR:
+ return "App Predictor";
+ case PACKAGE_WIFI:
+ return "Wi-Fi";
+ case PACKAGE_COMPANION:
+ return "Companion";
+ case PACKAGE_RETAIL_DEMO:
+ return "Retail Demo";
+ case PACKAGE_OVERLAY_CONFIG_SIGNATURE:
+ return "Overlay Config Signature";
+ case PACKAGE_RECENTS:
+ return "Recents";
+ case PACKAGE_AMBIENT_CONTEXT_DETECTION:
+ return "Ambient Context Detection";
+ }
+ return "Unknown";
+ }
+
+ String[] getKnownPackageNames(@NonNull Computer snapshot, int knownPackage, int userId) {
+ switch (knownPackage) {
+ case PACKAGE_BROWSER:
+ return new String[]{mDefaultAppProvider.getDefaultBrowser(userId)};
+ case PACKAGE_INSTALLER:
+ return snapshot.filterOnlySystemPackages(mRequiredInstallerPackage);
+ case PACKAGE_UNINSTALLER:
+ return snapshot.filterOnlySystemPackages(mRequiredUninstallerPackage);
+ case PACKAGE_SETUP_WIZARD:
+ return snapshot.filterOnlySystemPackages(mSetupWizardPackage);
+ case PACKAGE_SYSTEM:
+ return new String[]{"android"};
+ case PACKAGE_VERIFIER:
+ return snapshot.filterOnlySystemPackages(mRequiredVerifierPackage);
+ case PACKAGE_SYSTEM_TEXT_CLASSIFIER:
+ return snapshot.filterOnlySystemPackages(
+ mDefaultTextClassifierPackage, mSystemTextClassifierPackageName);
+ case PACKAGE_PERMISSION_CONTROLLER:
+ return snapshot.filterOnlySystemPackages(mRequiredPermissionControllerPackage);
+ case PACKAGE_CONFIGURATOR:
+ return snapshot.filterOnlySystemPackages(mConfiguratorPackage);
+ case PACKAGE_INCIDENT_REPORT_APPROVER:
+ return snapshot.filterOnlySystemPackages(mIncidentReportApproverPackage);
+ case PACKAGE_AMBIENT_CONTEXT_DETECTION:
+ return snapshot.filterOnlySystemPackages(mAmbientContextDetectionPackage);
+ case PACKAGE_APP_PREDICTOR:
+ return snapshot.filterOnlySystemPackages(mAppPredictionServicePackage);
+ case PACKAGE_COMPANION:
+ return snapshot.filterOnlySystemPackages(mCompanionPackage);
+ case PACKAGE_RETAIL_DEMO:
+ return TextUtils.isEmpty(mRetailDemoPackage)
+ ? ArrayUtils.emptyArray(String.class)
+ : new String[]{mRetailDemoPackage};
+ case PACKAGE_OVERLAY_CONFIG_SIGNATURE:
+ return snapshot.filterOnlySystemPackages(mOverlayConfigSignaturePackage);
+ case PACKAGE_RECENTS:
+ return snapshot.filterOnlySystemPackages(mRecentsPackage);
+ default:
+ return ArrayUtils.emptyArray(String.class);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 27c6d9bec2e8..af0a20ddf337 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -324,12 +324,12 @@ public class PackageDexOptimizer {
String compilerFilter = getRealCompilerFilter(pkg, options.getCompilerFilter());
// If the app is used by other apps, we must not use the existing profile because it
// may contain user data, unless the profile is newly created on install.
- final boolean resetProfile = isProfileGuidedCompilerFilter(compilerFilter)
+ final boolean useCloudProfile = isProfileGuidedCompilerFilter(compilerFilter)
&& isUsedByOtherApps
&& options.getCompilationReason() != PackageManagerService.REASON_INSTALL;
String dexMetadataPath = null;
- if (options.isDexoptInstallWithDexMetadata() || resetProfile) {
+ if (options.isDexoptInstallWithDexMetadata() || useCloudProfile) {
File dexMetadataFile = DexMetadataHelper.findDexMetadataForFile(new File(path));
dexMetadataPath = dexMetadataFile == null
? null : dexMetadataFile.getAbsolutePath();
@@ -339,65 +339,87 @@ public class PackageDexOptimizer {
// PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA which will be a no-op with respect to
// profiles.
int profileAnalysisResult = PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
- if (resetProfile) {
- if (!resetProfile(pkg, profileName, path, dexMetadataPath)) {
- // Fall back to use the shared filter.
- compilerFilter =
- PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
- PackageManagerService.REASON_SHARED);
- }
- } else if (options.isCheckForProfileUpdates()) {
+ if (options.isCheckForProfileUpdates()) {
profileAnalysisResult =
analyseProfiles(pkg, sharedGid, profileName, compilerFilter);
}
-
- // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct
- // flags.
- final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, resetProfile,
- options);
-
- for (String dexCodeIsa : dexCodeInstructionSets) {
- int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter,
- profileAnalysisResult, classLoaderContexts[i], dexoptFlags, sharedGid,
- packageStats, options.isDowngrade(), profileName, dexMetadataPath,
- options.getCompilationReason());
- // OTAPreopt doesn't have stats so don't report in that case.
- if (packageStats != null) {
- Trace.traceBegin(Trace.TRACE_TAG_PACKAGE_MANAGER, "dex2oat-metrics");
- try {
- long sessionId = sRandom.nextLong();
- ArtStatsLogUtils.writeStatsLog(
- mArtStatsLogger,
- sessionId,
- compilerFilter,
- pkg.getUid(),
- packageStats.getCompileTime(path),
- dexMetadataPath,
- options.getCompilationReason(),
- newResult,
- ArtStatsLogUtils.getApkType(path, pkg.getBaseApkPath(),
- pkg.getSplitCodePaths()),
- dexCodeIsa,
- path);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_PACKAGE_MANAGER);
+ String cloudProfileName = null;
+ try {
+ if (useCloudProfile) {
+ cloudProfileName = "cloud-" + profileName;
+ if (prepareCloudProfile(pkg, cloudProfileName, path, dexMetadataPath)) {
+ profileName = cloudProfileName;
+ } else {
+ // Fall back to use the shared filter.
+ compilerFilter =
+ PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
+ PackageManagerService.REASON_SHARED);
+ profileName = null;
}
+
+ // We still run `analyseProfiles` even if `useCloudProfile` is true because it
+ // merges profiles into the reference profile, which a system API
+ // `ArtManager.snapshotRuntimeProfile` takes snapshots from. However, we don't
+ // want the result to affect the decision of whether dexopt is needed.
+ profileAnalysisResult = PROFILE_ANALYSIS_DONT_OPTIMIZE_SMALL_DELTA;
}
- // Should stop the operation immediately.
- if (newResult == DEX_OPT_CANCELLED) {
- // Even for the cancellation, return failed if has failed.
- if (result == DEX_OPT_FAILED) {
- return result;
+ // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct
+ // flags.
+ final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter,
+ useCloudProfile, options);
+
+ for (String dexCodeIsa : dexCodeInstructionSets) {
+ int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter,
+ profileAnalysisResult, classLoaderContexts[i], dexoptFlags, sharedGid,
+ packageStats, options.isDowngrade(), profileName, dexMetadataPath,
+ options.getCompilationReason());
+ // OTAPreopt doesn't have stats so don't report in that case.
+ if (packageStats != null) {
+ Trace.traceBegin(Trace.TRACE_TAG_PACKAGE_MANAGER, "dex2oat-metrics");
+ try {
+ long sessionId = sRandom.nextLong();
+ ArtStatsLogUtils.writeStatsLog(
+ mArtStatsLogger,
+ sessionId,
+ compilerFilter,
+ pkg.getUid(),
+ packageStats.getCompileTime(path),
+ dexMetadataPath,
+ options.getCompilationReason(),
+ newResult,
+ ArtStatsLogUtils.getApkType(path, pkg.getBaseApkPath(),
+ pkg.getSplitCodePaths()),
+ dexCodeIsa,
+ path);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_PACKAGE_MANAGER);
+ }
+ }
+
+ // Should stop the operation immediately.
+ if (newResult == DEX_OPT_CANCELLED) {
+ // Even for the cancellation, return failed if has failed.
+ if (result == DEX_OPT_FAILED) {
+ return result;
+ }
+ return newResult;
+ }
+ // The end result is:
+ // - FAILED if any path failed,
+ // - PERFORMED if at least one path needed compilation,
+ // - SKIPPED when all paths are up to date
+ if ((result != DEX_OPT_FAILED) && (newResult != DEX_OPT_SKIPPED)) {
+ result = newResult;
}
- return newResult;
}
- // The end result is:
- // - FAILED if any path failed,
- // - PERFORMED if at least one path needed compilation,
- // - SKIPPED when all paths are up to date
- if ((result != DEX_OPT_FAILED) && (newResult != DEX_OPT_SKIPPED)) {
- result = newResult;
+ } finally {
+ if (cloudProfileName != null) {
+ try {
+ mInstaller.deleteReferenceProfile(pkg.getPackageName(), cloudProfileName);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to cleanup cloud profile", e);
+ }
}
}
}
@@ -405,22 +427,25 @@ public class PackageDexOptimizer {
}
/**
- * Resets the profiles of the dex file at {@code path} belonging to the package {@code pkg} to
- * the initial state as if the package is newly installed. Returns true on success, or false
- * otherwise.
+ * Creates a profile with the name {@code profileName} from the dex metadata file at {@code
+ * dexMetadataPath} for the dex file at {@code path} belonging to the package {@code pkg}.
+ *
+ * @return true on success, or false otherwise.
*/
@GuardedBy("mInstallLock")
- private boolean resetProfile(AndroidPackage pkg, String profileName, String path,
+ private boolean prepareCloudProfile(AndroidPackage pkg, String profileName, String path,
@Nullable String dexMetadataPath) {
if (dexMetadataPath != null) {
try {
- mInstaller.clearAppProfiles(pkg.getPackageName(), profileName);
+ // Make sure we don't keep any existing contents.
+ mInstaller.deleteReferenceProfile(pkg.getPackageName(), profileName);
+
final int appId = UserHandle.getAppId(pkg.getUid());
- mInstaller.prepareAppProfile(pkg.getPackageName(), UserHandle.USER_NULL,
- appId, profileName, path, dexMetadataPath);
+ mInstaller.prepareAppProfile(pkg.getPackageName(), UserHandle.USER_NULL, appId,
+ profileName, path, dexMetadataPath);
return true;
} catch (InstallerException e) {
- Slog.w(TAG, "Failed to reset profile", e);
+ Slog.w(TAG, "Failed to prepare cloud profile", e);
return false;
}
} else {
@@ -835,16 +860,16 @@ public class PackageDexOptimizer {
private int getDexFlags(ApplicationInfo info, String compilerFilter, DexoptOptions options) {
return getDexFlags((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0,
info.getHiddenApiEnforcementPolicy(), info.splitDependencies,
- info.requestsIsolatedSplitLoading(), compilerFilter, false /* resetProfile */,
+ info.requestsIsolatedSplitLoading(), compilerFilter, false /* useCloudProfile */,
options);
}
private int getDexFlags(AndroidPackage pkg, @NonNull PackageStateInternal pkgSetting,
- String compilerFilter, boolean resetProfile, DexoptOptions options) {
+ String compilerFilter, boolean useCloudProfile, DexoptOptions options) {
return getDexFlags(pkg.isDebuggable(),
AndroidPackageUtils.getHiddenApiEnforcementPolicy(pkg, pkgSetting),
pkg.getSplitDependencies(), pkg.isIsolatedSplitLoading(), compilerFilter,
- resetProfile, options);
+ useCloudProfile, options);
}
/**
@@ -853,15 +878,15 @@ public class PackageDexOptimizer {
*/
private int getDexFlags(boolean debuggable, int hiddenApiEnforcementPolicy,
SparseArray<int[]> splitDependencies, boolean requestsIsolatedSplitLoading,
- String compilerFilter, boolean resetProfile, DexoptOptions options) {
+ String compilerFilter, boolean useCloudProfile, DexoptOptions options) {
// Profile guide compiled oat files should not be public unles they are based
// on profiles from dex metadata archives.
// The flag isDexoptInstallWithDexMetadata applies only on installs when we know that
// the user does not have an existing profile.
- // The flag resetProfile applies only when the existing profile is already reset.
+ // The flag useCloudProfile applies only when the cloud profile should be used.
boolean isProfileGuidedFilter = isProfileGuidedCompilerFilter(compilerFilter);
boolean isPublic = !isProfileGuidedFilter || options.isDexoptInstallWithDexMetadata()
- || resetProfile;
+ || useCloudProfile;
int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0;
// Some apps are executed with restrictions on hidden API usage. If this app is one
// of them, pass a flag to dexopt to enable the same restrictions during compilation.
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 1efaa735a56c..7c900ef9401a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1741,7 +1741,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static boolean isSecureFrpInstallAllowed(Context context, int callingUid) {
final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
final String[] systemInstaller = pmi.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM);
+ KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM);
final AndroidPackage callingInstaller = pmi.getPackage(callingUid);
if (callingInstaller != null
&& ArrayUtils.contains(systemInstaller, callingInstaller.getPackageName())) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 4c7243decb07..6cf63d10f1f1 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -655,9 +655,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
final ProtectedPackages mProtectedPackages;
- @GuardedBy("mLoadedVolumes")
- final ArraySet<String> mLoadedVolumes = new ArraySet<>();
-
private boolean mFirstBoot;
final boolean mIsEngBuild;
@@ -667,7 +664,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
PackageManagerInternal.ExternalSourcesPolicy mExternalSourcesPolicy;
@GuardedBy("mAvailableFeatures")
- final ArrayMap<String, FeatureInfo> mAvailableFeatures;
+ private final ArrayMap<String, FeatureInfo> mAvailableFeatures;
@Watched
final InstantAppRegistry mInstantAppRegistry;
@@ -943,6 +940,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
private final DexOptHelper mDexOptHelper;
private final SuspendPackageHelper mSuspendPackageHelper;
private final IntentResolverInterceptor mIntentResolverInterceptor;
+ private final StorageEventHelper mStorageEventHelper;
/**
* Invalidate the package info cache, which includes updating the cached computer.
@@ -1584,7 +1582,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
}
/**
- * A extremely minimal constructor designed to start up a PackageManagerService instance for
+ * An extremely minimal constructor designed to start up a PackageManagerService instance for
* testing.
*
* It is assumed that all methods under test will mock the internal fields and thus
@@ -1689,6 +1687,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService
mSharedLibraries.setDeletePackageHelper(mDeletePackageHelper);
mIntentResolverInterceptor = null;
+ mStorageEventHelper = testParams.storageEventHelper;
registerObservers(false);
invalidatePackageInfoCache();
@@ -1841,6 +1840,8 @@ public class PackageManagerService implements PackageSender, TestUtilityService
mDexOptHelper = new DexOptHelper(this);
mSuspendPackageHelper = new SuspendPackageHelper(this, mInjector, mBroadcastHelper,
mProtectedPackages);
+ mStorageEventHelper = new StorageEventHelper(this, mDeletePackageHelper,
+ mRemovePackageHelper);
synchronized (mLock) {
// Create the computer as soon as the state objects have been installed. The
@@ -4055,17 +4056,15 @@ public class PackageManagerService implements PackageSender, TestUtilityService
mUserManager.systemReady();
// Watch for external volumes that come and go over time
- final StorageEventHelper storageEventHelper = new StorageEventHelper(this,
- mDeletePackageHelper, mRemovePackageHelper);
final StorageManager storage = mInjector.getSystemService(StorageManager.class);
- storage.registerListener(storageEventHelper);
+ storage.registerListener(mStorageEventHelper);
mInstallerService.systemReady();
mPackageDexOptimizer.systemReady();
// Now that we're mostly running, clean up stale users and apps
mUserManager.reconcileUsers(StorageManager.UUID_PRIVATE_INTERNAL);
- storageEventHelper.reconcileApps(snapshotComputer(), StorageManager.UUID_PRIVATE_INTERNAL);
+ mStorageEventHelper.reconcileApps(snapshotComputer(), StorageManager.UUID_PRIVATE_INTERNAL);
mPermissionManager.onSystemReady();
@@ -4163,20 +4162,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
}
}
- void dumpSnapshotStats(PrintWriter pw, boolean isBrief) {
- if (mSnapshotStatistics == null) {
- return;
- }
- int hits = 0;
- synchronized (mSnapshotLock) {
- if (mSnapshotComputer != null) {
- hits = mSnapshotComputer.getUsed();
- }
- }
- final long now = SystemClock.currentTimeMicro();
- mSnapshotStatistics.dump(pw, " ", now, hits, -1, isBrief);
- }
-
//TODO: b/111402650
private void disableSkuSpecificApps() {
String[] apkList = mContext.getResources().getStringArray(
@@ -4221,17 +4206,6 @@ public class PackageManagerService implements PackageSender, TestUtilityService
}
}
- /**
- * Verify that given package is currently frozen.
- */
- void checkPackageFrozen(String packageName) {
- synchronized (mLock) {
- if (!mFrozenPackages.containsKey(packageName)) {
- Slog.wtf(TAG, "Expected " + packageName + " to be frozen!", new Throwable());
- }
- }
- }
-
/** Called by UserManagerService */
void cleanUpUser(UserManagerService userManager, @UserIdInt int userId) {
synchronized (mLock) {
@@ -6050,7 +6024,37 @@ public class PackageManagerService implements PackageSender, TestUtilityService
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
- new DumpHelper(PackageManagerService.this).doDump(fd, pw, args);
+ final Computer snapshot = snapshotComputer();
+ final KnownPackages knownPackages = new KnownPackages(
+ mDefaultAppProvider,
+ mRequiredInstallerPackage,
+ mRequiredUninstallerPackage,
+ mSetupWizardPackage,
+ mRequiredVerifierPackage,
+ mDefaultTextClassifierPackage,
+ mSystemTextClassifierPackageName,
+ mRequiredPermissionControllerPackage,
+ mConfiguratorPackage,
+ mIncidentReportApproverPackage,
+ mAmbientContextDetectionPackage,
+ mAppPredictionServicePackage,
+ COMPANION_PACKAGE_NAME,
+ mRetailDemoPackage,
+ mOverlayConfigSignaturePackage,
+ mRecentsPackage);
+ final ArrayMap<String, FeatureInfo> availableFeatures;
+ synchronized (mAvailableFeatures) {
+ availableFeatures = new ArrayMap<>(mAvailableFeatures);
+ }
+ final ArraySet<String> protectedBroadcasts;
+ synchronized (mProtectedBroadcasts) {
+ protectedBroadcasts = new ArraySet<>(mProtectedBroadcasts);
+ }
+ new DumpHelper(mPermissionManager, mApexManager, mStorageEventHelper,
+ mDomainVerificationManager, mInstallerService, mRequiredVerifierPackage,
+ knownPackages, mChangedPackagesTracker, availableFeatures, protectedBroadcasts,
+ getPerUidReadTimeouts(snapshot)
+ ).doDump(snapshot, fd, pw, args);
}
}
@@ -6984,45 +6988,24 @@ public class PackageManagerService implements PackageSender, TestUtilityService
String[] getKnownPackageNamesInternal(@NonNull Computer snapshot, int knownPackage,
int userId) {
- switch (knownPackage) {
- case PackageManagerInternal.PACKAGE_BROWSER:
- return new String[] { mDefaultAppProvider.getDefaultBrowser(userId) };
- case PackageManagerInternal.PACKAGE_INSTALLER:
- return snapshot.filterOnlySystemPackages(mRequiredInstallerPackage);
- case PackageManagerInternal.PACKAGE_UNINSTALLER:
- return snapshot.filterOnlySystemPackages(mRequiredUninstallerPackage);
- case PackageManagerInternal.PACKAGE_SETUP_WIZARD:
- return snapshot.filterOnlySystemPackages(mSetupWizardPackage);
- case PackageManagerInternal.PACKAGE_SYSTEM:
- return new String[]{"android"};
- case PackageManagerInternal.PACKAGE_VERIFIER:
- return snapshot.filterOnlySystemPackages(mRequiredVerifierPackage);
- case PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER:
- return snapshot.filterOnlySystemPackages(
- mDefaultTextClassifierPackage, mSystemTextClassifierPackageName);
- case PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER:
- return snapshot.filterOnlySystemPackages(mRequiredPermissionControllerPackage);
- case PackageManagerInternal.PACKAGE_CONFIGURATOR:
- return snapshot.filterOnlySystemPackages(mConfiguratorPackage);
- case PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER:
- return snapshot.filterOnlySystemPackages(mIncidentReportApproverPackage);
- case PackageManagerInternal.PACKAGE_AMBIENT_CONTEXT_DETECTION:
- return snapshot.filterOnlySystemPackages(mAmbientContextDetectionPackage);
- case PackageManagerInternal.PACKAGE_APP_PREDICTOR:
- return snapshot.filterOnlySystemPackages(mAppPredictionServicePackage);
- case PackageManagerInternal.PACKAGE_COMPANION:
- return snapshot.filterOnlySystemPackages(COMPANION_PACKAGE_NAME);
- case PackageManagerInternal.PACKAGE_RETAIL_DEMO:
- return TextUtils.isEmpty(mRetailDemoPackage)
- ? ArrayUtils.emptyArray(String.class)
- : new String[] {mRetailDemoPackage};
- case PackageManagerInternal.PACKAGE_OVERLAY_CONFIG_SIGNATURE:
- return snapshot.filterOnlySystemPackages(mOverlayConfigSignaturePackage);
- case PackageManagerInternal.PACKAGE_RECENTS:
- return snapshot.filterOnlySystemPackages(mRecentsPackage);
- default:
- return ArrayUtils.emptyArray(String.class);
- }
+ return new KnownPackages(
+ mDefaultAppProvider,
+ mRequiredInstallerPackage,
+ mRequiredUninstallerPackage,
+ mSetupWizardPackage,
+ mRequiredVerifierPackage,
+ mDefaultTextClassifierPackage,
+ mSystemTextClassifierPackageName,
+ mRequiredPermissionControllerPackage,
+ mConfiguratorPackage,
+ mIncidentReportApproverPackage,
+ mAmbientContextDetectionPackage,
+ mAppPredictionServicePackage,
+ COMPANION_PACKAGE_NAME,
+ mRetailDemoPackage,
+ mOverlayConfigSignaturePackage,
+ mRecentsPackage)
+ .getKnownPackageNames(snapshot, knownPackage, userId);
}
String getActiveLauncherPackageName(int userId) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
index e466fe2c0e31..144231c95f75 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceTestParams.java
@@ -115,4 +115,5 @@ public final class PackageManagerServiceTestParams {
public ResolveIntentHelper resolveIntentHelper;
public DexOptHelper dexOptHelper;
public SuspendPackageHelper suspendPackageHelper;
+ public StorageEventHelper storageEventHelper;
}
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index b181cdd92379..baa3a9d85b0a 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -17,6 +17,7 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
+import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
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;
@@ -29,6 +30,7 @@ import static com.android.server.pm.PackageManagerService.TAG;
import android.annotation.NonNull;
import android.content.pm.PackageManager;
+import android.os.Trace;
import android.os.UserHandle;
import android.os.incremental.IncrementalManager;
import android.util.Log;
@@ -334,10 +336,19 @@ final class RemovePackageHelper {
mPm.mSettings.writeKernelMappingLPr(deletedPs);
}
}
+
if (removedAppId != -1) {
- // A user ID was deleted here. Go through all users and remove it
- // from KeyStore.
- mAppDataHelper.clearKeystoreData(UserHandle.USER_ALL, removedAppId);
+ // A user ID was deleted here. Go through all users and remove it from KeyStore.
+ final int appIdToRemove = removedAppId;
+ mPm.mInjector.getBackgroundHandler().post(() -> {
+ try {
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER,
+ "clearKeystoreData:" + appIdToRemove);
+ mAppDataHelper.clearKeystoreData(UserHandle.USER_ALL, appIdToRemove);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+ }
+ });
}
}
}
diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java
index a991ed3c4792..8c6b19b3361c 100644
--- a/services/core/java/com/android/server/pm/StorageEventHelper.java
+++ b/services/core/java/com/android/server/pm/StorageEventHelper.java
@@ -42,15 +42,19 @@ import android.os.storage.StorageManagerInternal;
import android.os.storage.VolumeInfo;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.policy.AttributeCache;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import java.io.File;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -61,6 +65,9 @@ public final class StorageEventHelper extends StorageEventListener {
private final DeletePackageHelper mDeletePackageHelper;
private final RemovePackageHelper mRemovePackageHelper;
+ @GuardedBy("mLoadedVolumes")
+ final ArraySet<String> mLoadedVolumes = new ArraySet<>();
+
// TODO(b/198166813): remove PMS dependency
public StorageEventHelper(PackageManagerService pm, DeletePackageHelper deletePackageHelper,
RemovePackageHelper removePackageHelper) {
@@ -216,8 +223,8 @@ public final class StorageEventHelper extends StorageEventListener {
if (DEBUG_INSTALL) Slog.d(TAG, "Loaded packages " + loaded);
sendResourcesChangedBroadcast(true, false, loaded, null);
- synchronized (mPm.mLoadedVolumes) {
- mPm.mLoadedVolumes.add(vol.getId());
+ synchronized (mLoadedVolumes) {
+ mLoadedVolumes.add(vol.getId());
}
}
@@ -267,8 +274,8 @@ public final class StorageEventHelper extends StorageEventListener {
if (DEBUG_INSTALL) Slog.d(TAG, "Unloaded packages " + unloaded);
sendResourcesChangedBroadcast(false, false, unloaded, null);
- synchronized (mPm.mLoadedVolumes) {
- mPm.mLoadedVolumes.remove(vol.getId());
+ synchronized (mLoadedVolumes) {
+ mLoadedVolumes.remove(vol.getId());
}
// Try very hard to release any references to this path so we don't risk
@@ -357,4 +364,24 @@ public final class StorageEventHelper extends StorageEventListener {
}
return codePaths;
}
+
+ public void dumpLoadedVolumes(@NonNull PrintWriter pw, @NonNull DumpState dumpState) {
+ if (dumpState.onTitlePrinted()) {
+ pw.println();
+ }
+ final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ", 120);
+ ipw.println();
+ ipw.println("Loaded volumes:");
+ ipw.increaseIndent();
+ synchronized (mLoadedVolumes) {
+ if (mLoadedVolumes.size() == 0) {
+ ipw.println("(none)");
+ } else {
+ for (int i = 0; i < mLoadedVolumes.size(); i++) {
+ ipw.println(mLoadedVolumes.valueAt(i));
+ }
+ }
+ }
+ ipw.decreaseIndent();
+ }
}
diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
index 588dfaf6db78..860c54c31bb2 100644
--- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java
+++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java
@@ -16,10 +16,6 @@
package com.android.server.pm;
-import static android.content.pm.PackageManagerInternal.PACKAGE_INSTALLER;
-import static android.content.pm.PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER;
-import static android.content.pm.PackageManagerInternal.PACKAGE_UNINSTALLER;
-import static android.content.pm.PackageManagerInternal.PACKAGE_VERIFIER;
import static android.os.Process.SYSTEM_UID;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
@@ -31,7 +27,6 @@ import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.IActivityManager;
import android.content.Intent;
-import android.content.pm.PackageManagerInternal.KnownPackage;
import android.content.pm.SuspendDialogInfo;
import android.os.Binder;
import android.os.Bundle;
@@ -489,13 +484,14 @@ public final class SuspendPackageHelper {
final String activeLauncherPackageName = defaultAppProvider.getDefaultHome(userId);
final String dialerPackageName = defaultAppProvider.getDefaultDialer(userId);
final String requiredInstallerPackage =
- getKnownPackageName(snapshot, PACKAGE_INSTALLER, userId);
+ getKnownPackageName(snapshot, KnownPackages.PACKAGE_INSTALLER, userId);
final String requiredUninstallerPackage =
- getKnownPackageName(snapshot, PACKAGE_UNINSTALLER, userId);
+ getKnownPackageName(snapshot, KnownPackages.PACKAGE_UNINSTALLER, userId);
final String requiredVerifierPackage =
- getKnownPackageName(snapshot, PACKAGE_VERIFIER, userId);
+ getKnownPackageName(snapshot, KnownPackages.PACKAGE_VERIFIER, userId);
final String requiredPermissionControllerPackage =
- getKnownPackageName(snapshot, PACKAGE_PERMISSION_CONTROLLER, userId);
+ getKnownPackageName(snapshot, KnownPackages.PACKAGE_PERMISSION_CONTROLLER,
+ userId);
for (int i = 0; i < packageNames.length; i++) {
canSuspend[i] = false;
final String packageName = packageNames[i];
@@ -638,8 +634,8 @@ public final class SuspendPackageHelper {
}
}
- private String getKnownPackageName(@NonNull Computer snapshot, @KnownPackage int knownPackage,
- int userId) {
+ private String getKnownPackageName(@NonNull Computer snapshot,
+ @KnownPackages.KnownPackage int knownPackage, int userId) {
final String[] knownPackages =
mPm.getKnownPackageNamesInternal(snapshot, knownPackage, userId);
return knownPackages.length > 0 ? knownPackages[0] : null;
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 36633cc635e7..849f53026c99 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -70,6 +70,7 @@ import com.android.internal.util.ArrayUtils;
import com.android.internal.util.XmlUtils;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
+import com.android.server.pm.KnownPackages;
import com.android.server.pm.permission.LegacyPermissionManagerInternal.PackagesProvider;
import com.android.server.pm.permission.LegacyPermissionManagerInternal.SyncAdapterPackagesProvider;
@@ -585,19 +586,19 @@ final class DefaultPermissionGrantPolicy {
// Installer
grantSystemFixedPermissionsToSystemPackage(pm,
ArrayUtils.firstOrNull(getKnownPackages(
- PackageManagerInternal.PACKAGE_INSTALLER, userId)),
+ KnownPackages.PACKAGE_INSTALLER, userId)),
userId, STORAGE_PERMISSIONS, NOTIFICATION_PERMISSIONS);
// Verifier
final String verifier = ArrayUtils.firstOrNull(getKnownPackages(
- PackageManagerInternal.PACKAGE_VERIFIER, userId));
+ KnownPackages.PACKAGE_VERIFIER, userId));
grantSystemFixedPermissionsToSystemPackage(pm, verifier, userId, STORAGE_PERMISSIONS);
grantPermissionsToSystemPackage(pm, verifier, userId, PHONE_PERMISSIONS, SMS_PERMISSIONS,
NOTIFICATION_PERMISSIONS);
// SetupWizard
final String setupWizardPackage = ArrayUtils.firstOrNull(getKnownPackages(
- PackageManagerInternal.PACKAGE_SETUP_WIZARD, userId));
+ KnownPackages.PACKAGE_SETUP_WIZARD, userId));
grantPermissionsToSystemPackage(pm, setupWizardPackage, userId, PHONE_PERMISSIONS,
CONTACTS_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS, CAMERA_PERMISSIONS);
grantSystemFixedPermissionsToSystemPackage(pm, setupWizardPackage, userId,
@@ -758,7 +759,7 @@ final class DefaultPermissionGrantPolicy {
// Browser
String browserPackage = ArrayUtils.firstOrNull(getKnownPackages(
- PackageManagerInternal.PACKAGE_BROWSER, userId));
+ KnownPackages.PACKAGE_BROWSER, userId));
if (browserPackage == null) {
browserPackage = getDefaultSystemHandlerActivityPackageForCategory(pm,
Intent.CATEGORY_APP_BROWSER, userId);
@@ -890,7 +891,7 @@ final class DefaultPermissionGrantPolicy {
// TextClassifier Service
for (String textClassifierPackage :
- getKnownPackages(PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER, userId)) {
+ getKnownPackages(KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER, userId)) {
grantPermissionsToSystemPackage(pm, textClassifierPackage, userId,
COARSE_BACKGROUND_LOCATION_PERMISSIONS, CONTACTS_PERMISSIONS);
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 009d155e96ef..c524fb7ae9e5 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -126,6 +126,7 @@ import com.android.server.ServiceThread;
import com.android.server.SystemConfig;
import com.android.server.Watchdog;
import com.android.server.pm.ApexManager;
+import com.android.server.pm.KnownPackages;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.PackageInfoUtils;
@@ -3323,7 +3324,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
@NonNull Permission bp) {
// expect single system package
String systemPackageName = ArrayUtils.firstOrNull(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM));
+ KnownPackages.PACKAGE_SYSTEM, UserHandle.USER_SYSTEM));
final AndroidPackage systemPackage =
mPackageManagerInt.getPackage(systemPackageName);
// check if the package is allow to use this signature permission. A package is allowed to
@@ -3398,10 +3399,10 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
// permissions are needed by the permission controller
if (!allowed && bp.isInstaller()
&& (ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM),
+ KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM),
pkg.getPackageName()) || ArrayUtils.contains(
mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER,
+ KnownPackages.PACKAGE_PERMISSION_CONTROLLER,
UserHandle.USER_SYSTEM), pkg.getPackageName()))) {
// If this permission is to be granted to the system installer and
// this app is an installer, then it gets the permission.
@@ -3409,7 +3410,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
}
if (!allowed && bp.isVerifier()
&& ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM),
+ KnownPackages.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM),
pkg.getPackageName())) {
// If this permission is to be granted to the system verifier and
// this app is a verifier, then it gets the permission.
@@ -3433,7 +3434,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
//}
if (!allowed && bp.isSetup()
&& ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM),
+ KnownPackages.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM),
pkg.getPackageName())) {
// If this permission is to be granted to the system setup wizard and
// this app is a setup wizard, then it gets the permission.
@@ -3441,21 +3442,21 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
}
if (!allowed && bp.isSystemTextClassifier()
&& ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_SYSTEM_TEXT_CLASSIFIER,
+ KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER,
UserHandle.USER_SYSTEM), pkg.getPackageName())) {
// Special permissions for the system default text classifier.
allowed = true;
}
if (!allowed && bp.isConfigurator()
&& ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_CONFIGURATOR,
+ KnownPackages.PACKAGE_CONFIGURATOR,
UserHandle.USER_SYSTEM), pkg.getPackageName())) {
// Special permissions for the device configurator.
allowed = true;
}
if (!allowed && bp.isIncidentReportApprover()
&& ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_INCIDENT_REPORT_APPROVER,
+ KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER,
UserHandle.USER_SYSTEM), pkg.getPackageName())) {
// If this permission is to be granted to the incident report approver and
// this app is the incident report approver, then it gets the permission.
@@ -3463,28 +3464,28 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
}
if (!allowed && bp.isAppPredictor()
&& ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM),
+ KnownPackages.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM),
pkg.getPackageName())) {
// Special permissions for the system app predictor.
allowed = true;
}
if (!allowed && bp.isCompanion()
&& ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_COMPANION, UserHandle.USER_SYSTEM),
+ KnownPackages.PACKAGE_COMPANION, UserHandle.USER_SYSTEM),
pkg.getPackageName())) {
// Special permissions for the system companion device manager.
allowed = true;
}
if (!allowed && bp.isRetailDemo()
&& ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM),
+ KnownPackages.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM),
pkg.getPackageName()) && isProfileOwner(pkg.getUid())) {
// Special permission granted only to the OEM specified retail demo app
allowed = true;
}
if (!allowed && bp.isRecents()
&& ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_RECENTS, UserHandle.USER_SYSTEM),
+ KnownPackages.PACKAGE_RECENTS, UserHandle.USER_SYSTEM),
pkg.getPackageName())) {
// Special permission for the recents app.
allowed = true;
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
index cf9370d12735..9aa53f18d0aa 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolver.java
@@ -47,13 +47,11 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import com.android.server.IntentResolver;
import com.android.server.pm.Computer;
-import com.android.server.pm.DumpState;
import com.android.server.pm.PackageManagerException;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.UserNeedsBadgingCache;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
-import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageStateUtils;
import com.android.server.pm.pkg.PackageUserStateInternal;
@@ -76,7 +74,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
@@ -271,119 +268,6 @@ public class ComponentResolver extends ComponentResolverLocked implements Snappa
}
}
- public void dumpActivityResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
- synchronized (mLock) {
- if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
- : "Activity Resolver Table:", " ", packageName,
- dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
- dumpState.setTitlePrinted(true);
- }
- }
- }
-
- public void dumpProviderResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
- synchronized (mLock) {
- if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
- : "Provider Resolver Table:", " ", packageName,
- dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
- dumpState.setTitlePrinted(true);
- }
- }
- }
-
- public void dumpReceiverResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
- synchronized (mLock) {
- if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
- : "Receiver Resolver Table:", " ", packageName,
- dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
- dumpState.setTitlePrinted(true);
- }
- }
- }
-
- public void dumpServiceResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
- synchronized (mLock) {
- if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
- : "Service Resolver Table:", " ", packageName,
- dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
- dumpState.setTitlePrinted(true);
- }
- }
- }
-
- public void dumpContentProviders(@NonNull Computer computer, PrintWriter pw,
- DumpState dumpState, String packageName) {
- synchronized (mLock) {
- boolean printedSomething = false;
- for (ParsedProvider p : mProviders.mProviders.values()) {
- if (packageName != null && !packageName.equals(p.getPackageName())) {
- continue;
- }
- if (!printedSomething) {
- if (dumpState.onTitlePrinted()) {
- pw.println();
- }
- pw.println("Registered ContentProviders:");
- printedSomething = true;
- }
- pw.print(" ");
- ComponentName.printShortString(pw, p.getPackageName(), p.getName());
- pw.println(":");
- pw.print(" ");
- pw.println(p.toString());
- }
- printedSomething = false;
- for (Map.Entry<String, ParsedProvider> entry :
- mProvidersByAuthority.entrySet()) {
- ParsedProvider p = entry.getValue();
- if (packageName != null && !packageName.equals(p.getPackageName())) {
- continue;
- }
- if (!printedSomething) {
- if (dumpState.onTitlePrinted()) {
- pw.println();
- }
- pw.println("ContentProvider Authorities:");
- printedSomething = true;
- }
- pw.print(" [");
- pw.print(entry.getKey());
- pw.println("]:");
- pw.print(" ");
- pw.println(p.toString());
-
- AndroidPackage pkg = computer.getPackage(p.getPackageName());
-
- if (pkg != null) {
- pw.print(" applicationInfo=");
- pw.println(AndroidPackageUtils.generateAppInfoWithoutState(pkg));
- }
- }
- }
- }
-
- public void dumpServicePermissions(PrintWriter pw, DumpState dumpState) {
- synchronized (mLock) {
- if (dumpState.onTitlePrinted()) pw.println();
- pw.println("Service permissions:");
-
- final Iterator<Pair<ParsedService, ParsedIntentInfo>> filterIterator =
- mServices.filterIterator();
- while (filterIterator.hasNext()) {
- final Pair<ParsedService, ParsedIntentInfo> pair = filterIterator.next();
- ParsedService service = pair.first;
-
- final String permission = service.getPermission();
- if (permission != null) {
- pw.print(" ");
- pw.print(service.getComponentName().flattenToShortString());
- pw.print(": ");
- pw.println(permission);
- }
- }
- }
- }
-
@GuardedBy("mLock")
private void addActivitiesLocked(@NonNull Computer computer, AndroidPackage pkg,
List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents, boolean chatty) {
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
index b6f2b2a0451b..b8e4c8d2a51f 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverApi.java
@@ -26,10 +26,12 @@ import android.content.pm.ResolveInfo;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.pm.Computer;
+import com.android.server.pm.DumpState;
import com.android.server.pm.pkg.component.ParsedActivity;
import com.android.server.pm.pkg.component.ParsedProvider;
import com.android.server.pm.pkg.component.ParsedService;
+import java.io.PrintWriter;
import java.util.List;
public interface ComponentResolverApi {
@@ -97,4 +99,21 @@ public interface ComponentResolverApi {
void querySyncProviders(@NonNull Computer computer, @NonNull List<String> outNames,
@NonNull List<ProviderInfo> outInfo, boolean safeMode, @UserIdInt int userId);
+
+ void dumpActivityResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName);
+
+ void dumpProviderResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName);
+
+ void dumpReceiverResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName);
+
+ void dumpServiceResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName);
+
+ void dumpContentProviders(@NonNull Computer computer, @NonNull PrintWriter pw,
+ @NonNull DumpState dumpState, @NonNull String packageName);
+
+ void dumpServicePermissions(@NonNull PrintWriter pw, @NonNull DumpState dumpState);
}
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
index 6b50fc6d306d..c01cecff9f61 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverBase.java
@@ -26,21 +26,28 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import android.os.UserHandle;
import android.util.ArrayMap;
+import android.util.Pair;
import com.android.server.pm.Computer;
+import com.android.server.pm.DumpState;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.PackageUserStateInternal;
import com.android.server.pm.pkg.component.ParsedActivity;
+import com.android.server.pm.pkg.component.ParsedIntentInfo;
import com.android.server.pm.pkg.component.ParsedMainComponent;
import com.android.server.pm.pkg.component.ParsedProvider;
import com.android.server.pm.pkg.component.ParsedService;
import com.android.server.utils.WatchableImpl;
+import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
public abstract class ComponentResolverBase extends WatchableImpl implements ComponentResolverApi {
@@ -305,4 +312,116 @@ public abstract class ComponentResolverBase extends WatchableImpl implements Com
outInfo.add(info);
}
}
+
+ @Override
+ public void dumpActivityResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName) {
+ if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
+ : "Activity Resolver Table:", " ", packageName,
+ dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+ dumpState.setTitlePrinted(true);
+ }
+ }
+
+ @Override
+ public void dumpProviderResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName) {
+ if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
+ : "Provider Resolver Table:", " ", packageName,
+ dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+ dumpState.setTitlePrinted(true);
+ }
+ }
+
+ @Override
+ public void dumpReceiverResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName) {
+ if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
+ : "Receiver Resolver Table:", " ", packageName,
+ dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+ dumpState.setTitlePrinted(true);
+ }
+ }
+
+ @Override
+ public void dumpServiceResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName) {
+ if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
+ : "Service Resolver Table:", " ", packageName,
+ dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+ dumpState.setTitlePrinted(true);
+ }
+ }
+
+ @Override
+ public void dumpContentProviders(@NonNull Computer computer, @NonNull PrintWriter pw,
+ @NonNull DumpState dumpState, @NonNull String packageName) {
+ boolean printedSomething = false;
+ for (ParsedProvider p : mProviders.mProviders.values()) {
+ if (packageName != null && !packageName.equals(p.getPackageName())) {
+ continue;
+ }
+ if (!printedSomething) {
+ if (dumpState.onTitlePrinted()) {
+ pw.println();
+ }
+ pw.println("Registered ContentProviders:");
+ printedSomething = true;
+ }
+ pw.print(" ");
+ ComponentName.printShortString(pw, p.getPackageName(), p.getName());
+ pw.println(":");
+ pw.print(" ");
+ pw.println(p.toString());
+ }
+ printedSomething = false;
+ for (Map.Entry<String, ParsedProvider> entry :
+ mProvidersByAuthority.entrySet()) {
+ ParsedProvider p = entry.getValue();
+ if (packageName != null && !packageName.equals(p.getPackageName())) {
+ continue;
+ }
+ if (!printedSomething) {
+ if (dumpState.onTitlePrinted()) {
+ pw.println();
+ }
+ pw.println("ContentProvider Authorities:");
+ printedSomething = true;
+ }
+ pw.print(" [");
+ pw.print(entry.getKey());
+ pw.println("]:");
+ pw.print(" ");
+ pw.println(p.toString());
+
+ AndroidPackage pkg = computer.getPackage(p.getPackageName());
+
+ if (pkg != null) {
+ pw.print(" applicationInfo=");
+ pw.println(AndroidPackageUtils.generateAppInfoWithoutState(pkg));
+ }
+ }
+ }
+
+ @Override
+ public void dumpServicePermissions(@NonNull PrintWriter pw, @NonNull DumpState dumpState) {
+ if (dumpState.onTitlePrinted()) pw.println();
+ pw.println("Service permissions:");
+
+ final Iterator<Pair<ParsedService, ParsedIntentInfo>> filterIterator =
+ mServices.filterIterator();
+ while (filterIterator.hasNext()) {
+ final Pair<ParsedService, ParsedIntentInfo> pair = filterIterator.next();
+ ParsedService service = pair.first;
+
+ final String permission = service.getPermission();
+ if (permission != null) {
+ pw.print(" ");
+ pw.print(service.getComponentName().flattenToShortString());
+ pw.print(": ");
+ pw.println(permission);
+ }
+ }
+ }
+
}
diff --git a/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java b/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
index ecc53ebf3d10..0c84f4c53dfe 100644
--- a/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
+++ b/services/core/java/com/android/server/pm/resolution/ComponentResolverLocked.java
@@ -25,12 +25,14 @@ import android.content.pm.ProviderInfo;
import android.content.pm.ResolveInfo;
import com.android.server.pm.Computer;
+import com.android.server.pm.DumpState;
import com.android.server.pm.PackageManagerTracedLock;
import com.android.server.pm.UserManagerService;
import com.android.server.pm.pkg.component.ParsedActivity;
import com.android.server.pm.pkg.component.ParsedProvider;
import com.android.server.pm.pkg.component.ParsedService;
+import java.io.PrintWriter;
import java.util.List;
public abstract class ComponentResolverLocked extends ComponentResolverBase {
@@ -189,4 +191,51 @@ public abstract class ComponentResolverLocked extends ComponentResolverBase {
super.querySyncProviders(computer, outNames, outInfo, safeMode, userId);
}
}
+
+ @Override
+ public void dumpActivityResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName) {
+ synchronized (mLock) {
+ super.dumpActivityResolvers(pw, dumpState, packageName);
+ }
+ }
+
+ @Override
+ public void dumpProviderResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName) {
+ synchronized (mLock) {
+ super.dumpProviderResolvers(pw, dumpState, packageName);
+ }
+ }
+
+ @Override
+ public void dumpReceiverResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName) {
+ synchronized (mLock) {
+ super.dumpReceiverResolvers(pw, dumpState, packageName);
+ }
+ }
+
+ @Override
+ public void dumpServiceResolvers(@NonNull PrintWriter pw, @NonNull DumpState dumpState,
+ @NonNull String packageName) {
+ synchronized (mLock) {
+ super.dumpServiceResolvers(pw, dumpState, packageName);
+ }
+ }
+
+ @Override
+ public void dumpContentProviders(@NonNull Computer computer, @NonNull PrintWriter pw,
+ @NonNull DumpState dumpState, @NonNull String packageName) {
+ synchronized (mLock) {
+ super.dumpContentProviders(computer, pw, dumpState, packageName);
+ }
+ }
+
+ @Override
+ public void dumpServicePermissions(@NonNull PrintWriter pw, @NonNull DumpState dumpState) {
+ synchronized (mLock) {
+ super.dumpServicePermissions(pw, dumpState);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/utils/WatchedArraySet.java b/services/core/java/com/android/server/utils/WatchedArraySet.java
index 5070dd1675d3..ec80261a2196 100644
--- a/services/core/java/com/android/server/utils/WatchedArraySet.java
+++ b/services/core/java/com/android/server/utils/WatchedArraySet.java
@@ -20,6 +20,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.ArraySet;
+import java.util.Collection;
+
/**
* WatchedArraySet is an {@link android.util.ArraySet} that can report changes to itself. If its
* values are {@link Watchable} then the WatchedArraySet will also report changes to the values.
@@ -280,13 +282,11 @@ public class WatchedArraySet<E> extends WatchableImpl
/**
* Perform a {@link #add(Object)} of all values in <var>array</var>
- * @param array The array whose contents are to be retrieved.
+ * @param collection The collection whose contents are to be retrieved.
*/
- public void addAll(ArraySet<? extends E> array) {
- final int end = array.size();
- for (int i = 0; i < end; i++) {
- add(array.valueAt(i));
- }
+ public void addAll(Collection<? extends E> collection) {
+ mStorage.addAll(collection);
+ onChanged();
}
/**
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 8018d5652b1b..5fdcd690b5e2 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -85,6 +85,7 @@ import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.LocalServices;
import com.android.server.Watchdog;
+import com.android.server.pm.KnownPackages;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.uri.NeededUriGrants;
import com.android.server.vr.VrManagerInternal;
@@ -627,7 +628,7 @@ class ActivityClientController extends IActivityClientController.Stub {
return true;
}
final String[] installerNames = pm.getKnownPackageNames(
- PackageManagerInternal.PACKAGE_INSTALLER, UserHandle.getUserId(uid));
+ KnownPackages.PACKAGE_INSTALLER, UserHandle.getUserId(uid));
return installerNames.length > 0 && callingPkg.getPackageName().equals(installerNames[0]);
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 52651b9fd076..798719b9c51f 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -53,6 +53,7 @@ import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
+import static android.view.ViewRootImpl.LOCAL_LAYOUT;
import static android.view.WindowInsets.Type.displayCutout;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.systemBars;
@@ -2647,29 +2648,27 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mCurrentPrivacyIndicatorBounds =
mCurrentPrivacyIndicatorBounds.updateStaticBounds(staticBounds);
if (!Objects.equals(oldBounds, mCurrentPrivacyIndicatorBounds)) {
- final DisplayInfo info = mDisplayInfo;
- if (mDisplayFrames.onDisplayInfoUpdated(info,
- calculateDisplayCutoutForRotation(info.rotation),
- calculateRoundedCornersForRotation(info.rotation),
- calculatePrivacyIndicatorBoundsForRotation(info.rotation))) {
- mInsetsStateController.onDisplayInfoUpdated(true);
- }
+ updateDisplayFrames(false /* insetsSourceMayChange */, true /* notifyInsetsChange */);
}
}
void onDisplayInfoChanged() {
- final DisplayInfo info = mDisplayInfo;
- if (mDisplayFrames.onDisplayInfoUpdated(info,
- calculateDisplayCutoutForRotation(info.rotation),
- calculateRoundedCornersForRotation(info.rotation),
- calculatePrivacyIndicatorBoundsForRotation(info.rotation))) {
- // TODO(b/161810301): Set notifyInsetsChange to true while the server no longer performs
- // layout.
- mInsetsStateController.onDisplayInfoUpdated(false /* notifyInsetsChanged */);
- }
+ updateDisplayFrames(LOCAL_LAYOUT, LOCAL_LAYOUT);
mMinSizeOfResizeableTaskDp = getMinimalTaskSizeDp();
- mInputMonitor.layoutInputConsumers(info.logicalWidth, info.logicalHeight);
- mDisplayPolicy.onDisplayInfoChanged(info);
+ mInputMonitor.layoutInputConsumers(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+ mDisplayPolicy.onDisplayInfoChanged(mDisplayInfo);
+ }
+
+ private void updateDisplayFrames(boolean insetsSourceMayChange, boolean notifyInsetsChange) {
+ if (mDisplayFrames.update(mDisplayInfo,
+ calculateDisplayCutoutForRotation(mDisplayInfo.rotation),
+ calculateRoundedCornersForRotation(mDisplayInfo.rotation),
+ calculatePrivacyIndicatorBoundsForRotation(mDisplayInfo.rotation))) {
+ if (insetsSourceMayChange) {
+ mDisplayPolicy.updateInsetsSourceFramesExceptIme(mDisplayFrames);
+ }
+ mInsetsStateController.onDisplayFramesUpdated(notifyInsetsChange);
+ }
}
@Override
@@ -3979,6 +3978,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
ProtoLog.i(WM_DEBUG_IME, "setInputMethodTarget %s", target);
+ final boolean layeringTargetChanged = target != mImeLayeringTarget;
mImeLayeringTarget = target;
// 1. Reparent the IME container window to the target root DA to get the correct bounds and
@@ -4006,7 +4006,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// 4. Update the IME control target to apply any inset change and animation.
// 5. Reparent the IME container surface to either the input target app, or the IME window
// parent.
- updateImeControlTarget(true /* forceUpdateImeParent */);
+ updateImeControlTarget(layeringTargetChanged);
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java
index 45d7141fd556..76aa7f963aa6 100644
--- a/services/core/java/com/android/server/wm/DisplayFrames.java
+++ b/services/core/java/com/android/server/wm/DisplayFrames.java
@@ -64,26 +64,26 @@ public class DisplayFrames {
PrivacyIndicatorBounds indicatorBounds) {
mDisplayId = displayId;
mInsetsState = insetsState;
- onDisplayInfoUpdated(info, displayCutout, roundedCorners, indicatorBounds);
+ update(info, displayCutout, roundedCorners, indicatorBounds);
}
/**
- * Update {@link DisplayFrames} when {@link DisplayInfo} is updated.
+ * This is called when {@link DisplayInfo} or {@link PrivacyIndicatorBounds} is updated.
*
* @param info the updated {@link DisplayInfo}.
* @param displayCutout the updated {@link DisplayCutout}.
* @param roundedCorners the updated {@link RoundedCorners}.
- * @return {@code true} if the insets state has been changed; {@code false} otherwise.
+ * @param indicatorBounds the updated {@link PrivacyIndicatorBounds}.
+ * @return {@code true} if anything has been changed; {@code false} otherwise.
*/
- public boolean onDisplayInfoUpdated(DisplayInfo info, @NonNull WmDisplayCutout displayCutout,
+ public boolean update(DisplayInfo info, @NonNull WmDisplayCutout displayCutout,
@NonNull RoundedCorners roundedCorners,
@NonNull PrivacyIndicatorBounds indicatorBounds) {
- mRotation = info.rotation;
-
final InsetsState state = mInsetsState;
final Rect safe = mDisplayCutoutSafe;
final DisplayCutout cutout = displayCutout.getDisplayCutout();
if (mDisplayWidth == info.logicalWidth && mDisplayHeight == info.logicalHeight
+ && mRotation != info.rotation
&& state.getDisplayCutout().equals(cutout)
&& state.getRoundedCorners().equals(roundedCorners)
&& state.getPrivacyIndicatorBounds().equals(indicatorBounds)) {
@@ -91,6 +91,7 @@ public class DisplayFrames {
}
mDisplayWidth = info.logicalWidth;
mDisplayHeight = info.logicalHeight;
+ mRotation = info.rotation;
final Rect unrestricted = mUnrestricted;
unrestricted.set(0, 0, mDisplayWidth, mDisplayHeight);
state.setDisplayFrame(unrestricted);
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 4573ede13f7f..3d826bf99df0 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1498,10 +1498,6 @@ public class DisplayPolicy {
}
}
- // TODO(b/161810301): No one is calling this since we haven't moved window layout to the client.
- // When that happens, this should be called when the display rotation is
- // changed, so that we can dispatch the correct insets to all the clients
- // before the insets source windows report their frames to the server.
void updateInsetsSourceFramesExceptIme(DisplayFrames displayFrames) {
for (int i = mInsetsSourceWindowsExceptIme.size() - 1; i >= 0; i--) {
final WindowState win = mInsetsSourceWindowsExceptIme.valueAt(i);
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index a19d72e37124..ed771c202c04 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -177,7 +177,7 @@ class InsetsStateController {
}
}
- void onDisplayInfoUpdated(boolean notifyInsetsChange) {
+ void onDisplayFramesUpdated(boolean notifyInsetsChange) {
final ArrayList<WindowState> insetsChangedWindows = new ArrayList<>();
mDisplayContent.forAllWindows(w -> {
w.mAboveInsetsState.set(mState, displayCutout());
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 0542c0be5790..5918a88d5736 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -26,7 +26,6 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
-import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
@@ -4341,9 +4340,7 @@ class Task extends TaskFragment {
int elevation = 0;
// Get elevation for a specific windowing mode.
- if (inPinnedWindowingMode()) {
- elevation = PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
- } else if (inFreeformWindowingMode()) {
+ if (inFreeformWindowingMode()) {
elevation = taskIsFocused
? DECOR_SHADOW_FOCUSED_HEIGHT_IN_DIP : DECOR_SHADOW_UNFOCUSED_HEIGHT_IN_DIP;
} else {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 4175da89cf8b..7d3c784e4f16 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -278,7 +278,6 @@ import android.net.wifi.WifiManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
-import android.os.CancellationSignal;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
@@ -7235,47 +7234,45 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkState(admin != null,
"Lost mode location updates can only be sent on an organization-owned device.");
mInjector.binderWithCleanCallingIdentity(() -> {
- final List<String> providers =
- mInjector.getLocationManager().getAllProviders().stream()
- .filter(mInjector.getLocationManager()::isProviderEnabled)
- .collect(Collectors.toList());
- if (providers.isEmpty()) {
- future.complete(false);
- return;
- }
-
- final CancellationSignal cancellationSignal = new CancellationSignal();
- List<String> providersWithNullLocation = new ArrayList<String>();
- for (String provider : providers) {
- mInjector.getLocationManager().getCurrentLocation(provider, cancellationSignal,
- mContext.getMainExecutor(), location -> {
- if (cancellationSignal.isCanceled()) {
- return;
- } else if (location != null) {
- sendLostModeLocationUpdate(admin, location);
- cancellationSignal.cancel();
- future.complete(true);
- } else {
- // location == null, provider wasn't able to get location, see
- // if there are more providers
- providersWithNullLocation.add(provider);
- if (providers.size() == providersWithNullLocation.size()) {
- future.complete(false);
- }
- }
- }
- );
- }
+ String[] providers = {LocationManager.FUSED_PROVIDER,
+ LocationManager.NETWORK_PROVIDER, LocationManager.GPS_PROVIDER};
+ tryRetrieveAndSendLocationUpdate(admin, future, providers, /* index= */ 0);
});
}
}
- private void sendLostModeLocationUpdate(ActiveAdmin admin, Location location) {
+ /** Send lost mode location updates recursively, in order of the list of location providers. */
+ private void tryRetrieveAndSendLocationUpdate(ActiveAdmin admin,
+ AndroidFuture<Boolean> future, String[] providers, int index) {
+ // None of the providers were able to get location, return false
+ if (index == providers.length) {
+ future.complete(false);
+ return;
+ }
+ if (mInjector.getLocationManager().isProviderEnabled(providers[index])) {
+ mInjector.getLocationManager().getCurrentLocation(providers[index],
+ /* cancellationSignal= */ null, mContext.getMainExecutor(), location -> {
+ if (location != null) {
+ mContext.sendBroadcastAsUser(
+ newLostModeLocationUpdateIntent(admin, location),
+ admin.getUserHandle());
+ future.complete(true);
+ } else {
+ tryRetrieveAndSendLocationUpdate(admin, future, providers, index + 1);
+ }
+ }
+ );
+ } else {
+ tryRetrieveAndSendLocationUpdate(admin, future, providers, index + 1);
+ }
+ }
+
+ private Intent newLostModeLocationUpdateIntent(ActiveAdmin admin, Location location) {
final Intent intent = new Intent(
DevicePolicyManager.ACTION_LOST_MODE_LOCATION_UPDATE);
intent.putExtra(DevicePolicyManager.EXTRA_LOST_MODE_LOCATION, location);
intent.setPackage(admin.info.getPackageName());
- mContext.sendBroadcastAsUser(intent, admin.getUserHandle());
+ return intent;
}
/**
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index 4a51e41b1dc5..c9523ec16b8f 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -58,6 +58,7 @@ import static com.android.server.alarm.Alarm.EXACT_ALLOW_REASON_PERMISSION;
import static com.android.server.alarm.AlarmManagerService.ACTIVE_INDEX;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.APP_STANDBY_BUCKET_CHANGED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHARGING_STATUS_CHANGED;
+import static com.android.server.alarm.AlarmManagerService.AlarmHandler.CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_ADDED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.EXACT_ALARM_DENY_LIST_PACKAGES_REMOVED;
import static com.android.server.alarm.AlarmManagerService.AlarmHandler.REFRESH_EXACT_ALARM_CANDIDATES;
@@ -1044,9 +1045,19 @@ public class AlarmManagerServiceTest {
final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
verify(mService.mHandler, atLeastOnce()).sendMessageAtTime(messageCaptor.capture(),
anyLong());
- final Message lastMessage = messageCaptor.getValue();
- assertEquals("Unexpected message send to handler", what, lastMessage.what);
- mService.mHandler.handleMessage(lastMessage);
+
+ Message expectedMessage = null;
+ final ArrayList<Integer> sentMessages = new ArrayList<>();
+ for (Message sentMessage : messageCaptor.getAllValues()) {
+ if (sentMessage.what == what) {
+ expectedMessage = sentMessage;
+ }
+ sentMessages.add(sentMessage.what);
+ }
+
+ assertNotNull("Unexpected messages sent to handler. Expected: " + what + ", sent: "
+ + sentMessages, expectedMessage);
+ mService.mHandler.handleMessage(expectedMessage);
}
@Test
@@ -2109,16 +2120,16 @@ public class AlarmManagerServiceTest {
public void hasScheduleExactAlarmBinderCallNotDenyListed() throws RemoteException {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
- mockExactAlarmPermissionGrant(true, false, MODE_DEFAULT);
+ mockScheduleExactAlarmState(true, false, MODE_DEFAULT);
assertTrue(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
- mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
+ mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
assertTrue(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
- mockExactAlarmPermissionGrant(true, false, MODE_IGNORED);
+ mockScheduleExactAlarmState(true, false, MODE_IGNORED);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
}
@@ -2126,16 +2137,16 @@ public class AlarmManagerServiceTest {
public void hasScheduleExactAlarmBinderCallDenyListed() throws RemoteException {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
- mockExactAlarmPermissionGrant(true, true, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, true, MODE_ERRORED);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
- mockExactAlarmPermissionGrant(true, true, MODE_DEFAULT);
+ mockScheduleExactAlarmState(true, true, MODE_DEFAULT);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
- mockExactAlarmPermissionGrant(true, true, MODE_IGNORED);
+ mockScheduleExactAlarmState(true, true, MODE_IGNORED);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
- mockExactAlarmPermissionGrant(true, true, MODE_ALLOWED);
+ mockScheduleExactAlarmState(true, true, MODE_ALLOWED);
assertTrue(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
}
@@ -2148,13 +2159,13 @@ public class AlarmManagerServiceTest {
public void hasScheduleExactAlarmBinderCallNotDeclared() throws RemoteException {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
- mockExactAlarmPermissionGrant(false, false, MODE_DEFAULT);
+ mockScheduleExactAlarmState(false, false, MODE_DEFAULT);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
- mockExactAlarmPermissionGrant(false, false, MODE_ALLOWED);
+ mockScheduleExactAlarmState(false, false, MODE_ALLOWED);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
- mockExactAlarmPermissionGrant(false, true, MODE_ALLOWED);
+ mockScheduleExactAlarmState(false, true, MODE_ALLOWED);
assertFalse(mBinder.hasScheduleExactAlarm(TEST_CALLING_PACKAGE, TEST_CALLING_USER));
}
@@ -2162,10 +2173,17 @@ public class AlarmManagerServiceTest {
public void canScheduleExactAlarmsBinderCallChangeDisabled() throws RemoteException {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
- mockExactAlarmPermissionGrant(false, true, MODE_DEFAULT);
+ // canScheduleExactAlarms should be true regardless of any permission state.
+ mockUseExactAlarmState(true);
assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockUseExactAlarmState(false);
+ assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
+
+ mockScheduleExactAlarmState(false, true, MODE_DEFAULT);
+ assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
+
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
}
@@ -2173,44 +2191,45 @@ public class AlarmManagerServiceTest {
public void canScheduleExactAlarmsBinderCall() throws RemoteException {
// Policy permission is denied in setUp().
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+ mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true);
// No permission, no exemption.
- mockExactAlarmPermissionGrant(true, true, MODE_DEFAULT);
+ mockScheduleExactAlarmState(true, true, MODE_DEFAULT);
assertFalse(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
// No permission, no exemption.
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
assertFalse(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
// Policy permission only, no exemption.
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
- doReturn(PermissionChecker.PERMISSION_GRANTED).when(
- () -> PermissionChecker.checkPermissionForPreflight(eq(mMockContext),
- eq(Manifest.permission.USE_EXACT_ALARM), anyInt(), eq(TEST_CALLING_UID),
- eq(TEST_CALLING_PACKAGE)));
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
+ mockUseExactAlarmState(true);
assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
- // Permission, no exemption.
- mockExactAlarmPermissionGrant(true, false, MODE_DEFAULT);
+ mockUseExactAlarmState(false);
+
+ // User permission only, no exemption.
+ mockScheduleExactAlarmState(true, false, MODE_DEFAULT);
assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
- // Permission, no exemption.
- mockExactAlarmPermissionGrant(true, true, MODE_ALLOWED);
+ // User permission only, no exemption.
+ mockScheduleExactAlarmState(true, true, MODE_ALLOWED);
assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
// No permission, exemption.
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(TEST_CALLING_UID)).thenReturn(true);
assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
// No permission, exemption.
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(TEST_CALLING_UID)).thenReturn(false);
doReturn(true).when(() -> UserHandle.isCore(TEST_CALLING_UID));
assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
- // Both permission and exemption.
- mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
+ // Both permissions and exemption.
+ mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
+ mockUseExactAlarmState(true);
assertTrue(mBinder.canScheduleExactAlarms(TEST_CALLING_PACKAGE));
}
@@ -2237,6 +2256,8 @@ public class AlarmManagerServiceTest {
verify(mService, never()).hasScheduleExactAlarmInternal(TEST_CALLING_PACKAGE,
TEST_CALLING_UID);
+ verify(mService, never()).hasUseExactAlarmInternal(TEST_CALLING_PACKAGE,
+ TEST_CALLING_UID);
verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());
}
@@ -2313,7 +2334,7 @@ public class AlarmManagerServiceTest {
public void alarmClockBinderCall() throws RemoteException {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
- mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
+ mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
final PendingIntent alarmPi = getNewMockPendingIntent();
final AlarmManager.AlarmClockInfo alarmClock = mock(AlarmManager.AlarmClockInfo.class);
@@ -2335,7 +2356,7 @@ public class AlarmManagerServiceTest {
assertEquals(TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED, type);
}
- private void mockExactAlarmPermissionGrant(boolean declared, boolean denyList, int mode) {
+ private void mockScheduleExactAlarmState(boolean declared, boolean denyList, int mode) {
String[] requesters = declared ? new String[]{TEST_CALLING_PACKAGE} : EmptyArray.STRING;
when(mPermissionManagerInternal.getAppOpPermissionPackages(SCHEDULE_EXACT_ALARM))
.thenReturn(requesters);
@@ -2350,12 +2371,21 @@ public class AlarmManagerServiceTest {
TEST_CALLING_PACKAGE)).thenReturn(mode);
}
+ private void mockUseExactAlarmState(boolean granted) {
+ final int result = granted ? PermissionChecker.PERMISSION_GRANTED
+ : PermissionChecker.PERMISSION_HARD_DENIED;
+ doReturn(result).when(
+ () -> PermissionChecker.checkPermissionForPreflight(eq(mMockContext),
+ eq(Manifest.permission.USE_EXACT_ALARM), anyInt(), eq(TEST_CALLING_UID),
+ eq(TEST_CALLING_PACKAGE)));
+ }
+
@Test
public void alarmClockBinderCallWithoutPermission() throws RemoteException {
setDeviceConfigBoolean(KEY_CRASH_NON_CLOCK_APPS, true);
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
final PendingIntent alarmPi = getNewMockPendingIntent();
@@ -2377,7 +2407,7 @@ public class AlarmManagerServiceTest {
public void exactBinderCallWithPermission() throws RemoteException {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
- mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
+ mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
final PendingIntent alarmPi = getNewMockPendingIntent();
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
0, alarmPi, null, null, null, null);
@@ -2401,7 +2431,7 @@ public class AlarmManagerServiceTest {
public void exactBinderCallWithAllowlist() throws RemoteException {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
// If permission is denied, only then allowlist will be checked.
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
final PendingIntent alarmPi = getNewMockPendingIntent();
@@ -2421,7 +2451,7 @@ public class AlarmManagerServiceTest {
public void exactAllowWhileIdleBinderCallWithPermission() throws RemoteException {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
- mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
+ mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
final PendingIntent alarmPi = getNewMockPendingIntent();
mBinder.set(TEST_CALLING_PACKAGE, ELAPSED_REALTIME_WAKEUP, 1234, WINDOW_EXACT, 0,
FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null);
@@ -2444,7 +2474,7 @@ public class AlarmManagerServiceTest {
public void exactAllowWhileIdleBinderCallWithAllowlist() throws RemoteException {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
// If permission is denied, only then allowlist will be checked.
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
final PendingIntent alarmPi = getNewMockPendingIntent();
@@ -2471,7 +2501,7 @@ public class AlarmManagerServiceTest {
setDeviceConfigBoolean(KEY_CRASH_NON_CLOCK_APPS, true);
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(false);
final PendingIntent alarmPi = getNewMockPendingIntent();
@@ -2503,6 +2533,7 @@ public class AlarmManagerServiceTest {
FLAG_ALLOW_WHILE_IDLE, alarmPi, null, null, null, null);
verify(mService, never()).hasScheduleExactAlarmInternal(anyString(), anyInt());
+ verify(mService, never()).hasUseExactAlarmInternal(anyString(), anyInt());
verify(mDeviceIdleInternal, never()).isAppOnWhitelist(anyInt());
final ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
@@ -2520,7 +2551,7 @@ public class AlarmManagerServiceTest {
public void binderCallWithUserAllowlist() throws RemoteException {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
when(mDeviceIdleInternal.isAppOnWhitelist(anyInt())).thenReturn(true);
when(mAppStateTracker.isUidPowerSaveUserExempt(TEST_CALLING_UID)).thenReturn(true);
@@ -2792,7 +2823,7 @@ public class AlarmManagerServiceTest {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ALLOWED);
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
assertAndHandleMessageSync(REMOVE_EXACT_ALARMS);
@@ -2805,7 +2836,7 @@ public class AlarmManagerServiceTest {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ALLOWED);
- mockExactAlarmPermissionGrant(true, false, MODE_ERRORED);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
@@ -2818,7 +2849,7 @@ public class AlarmManagerServiceTest {
mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, false);
mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ERRORED);
- mockExactAlarmPermissionGrant(true, true, MODE_DEFAULT);
+ mockScheduleExactAlarmState(true, true, MODE_DEFAULT);
mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
@@ -2834,7 +2865,7 @@ public class AlarmManagerServiceTest {
when(mActivityManagerInternal.getBootTimeTempAllowListDuration()).thenReturn(durationMs);
mService.mLastOpScheduleExactAlarm.put(TEST_CALLING_UID, MODE_ERRORED);
- mockExactAlarmPermissionGrant(true, false, MODE_ALLOWED);
+ mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
mIAppOpsCallback.opChanged(OP_SCHEDULE_EXACT_ALARM, TEST_CALLING_UID, TEST_CALLING_PACKAGE);
final ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -3036,48 +3067,6 @@ public class AlarmManagerServiceTest {
}
@Test
- public void refreshExactAlarmCandidatesRemovesExactAlarmsIfNeeded() {
- mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
-
- mService.mExactAlarmCandidates = new ArraySet<>(new Integer[]{1, 2, 5});
- final String[] updatedRequesters = new String[]{"p11", "p2", "p9"};
- final Integer[] appIds = new Integer[]{11, 2, 9};
- registerAppIds(updatedRequesters, appIds);
-
- when(mPermissionManagerInternal.getAppOpPermissionPackages(
- SCHEDULE_EXACT_ALARM)).thenReturn(updatedRequesters);
-
- final PendingIntent exactAppId1 = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME, 0, 0, exactAppId1, 0, 0,
- UserHandle.getUid(TEST_CALLING_USER, 1), null);
-
- final PendingIntent exactAppId2 = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME, 0, 0, exactAppId2, 0, 0,
- UserHandle.getUid(TEST_CALLING_USER, 2), null);
-
- final PendingIntent exactAppId5 = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME, 0, 0, exactAppId5, 0, 0,
- UserHandle.getUid(TEST_CALLING_USER, 5), null);
-
- final PendingIntent inexactAppId5 = getNewMockPendingIntent();
- setTestAlarm(ELAPSED_REALTIME, 0, 23, inexactAppId5, 0, 0,
- UserHandle.getUid(TEST_CALLING_USER, 5), null);
-
- assertEquals(4, mService.mAlarmStore.size());
-
- mService.refreshExactAlarmCandidates();
- // App ids 1 and 5 lost the permission, so there alarms should be removed.
-
- final ArrayList<Alarm> remaining = mService.mAlarmStore.asList();
- assertEquals(2, remaining.size());
-
- assertTrue("Inexact alarm removed",
- remaining.removeIf(a -> a.matches(inexactAppId5, null)));
- assertTrue("Alarm from app id 2 removed",
- remaining.removeIf(a -> a.matches(exactAppId2, null)));
- }
-
- @Test
public void refreshExactAlarmCandidatesOnPackageAdded() {
final String[] exactAlarmRequesters = new String[]{"p11", "p2", "p9"};
final Integer[] appIds = new Integer[]{11, 2, 9};
@@ -3130,6 +3119,78 @@ public class AlarmManagerServiceTest {
}
@Test
+ public void exactAlarmsRemovedIfNeededOnPackageReplaced() {
+ mockChangeEnabled(AlarmManager.REQUIRE_EXACT_ALARM_PERMISSION, true);
+ mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true);
+
+ final int otherUid = 2313;
+ final String otherPackage = "p1";
+
+ final PendingIntent exactAlarm1 = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, 1, 0, exactAlarm1, 0, 0, TEST_CALLING_UID,
+ TEST_CALLING_PACKAGE, null);
+
+ final PendingIntent exactAlarm2 = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, 2, 0, exactAlarm2, 0, 0, TEST_CALLING_UID,
+ TEST_CALLING_PACKAGE, null);
+
+ final PendingIntent otherPackageExactAlarm = getNewMockPendingIntent(otherUid,
+ otherPackage);
+ setTestAlarm(ELAPSED_REALTIME, 0, 0, otherPackageExactAlarm, 0, 0, otherUid, otherPackage,
+ null);
+
+ final PendingIntent inexactAlarm = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, 0, 23, inexactAlarm, 0, 0, TEST_CALLING_UID,
+ TEST_CALLING_PACKAGE, null);
+
+ final PendingIntent otherPackageInexactAlarm = getNewMockPendingIntent(otherUid,
+ otherPackage);
+ setTestAlarm(ELAPSED_REALTIME, 0, 23, otherPackageInexactAlarm, 0, 0, otherUid,
+ otherPackage, null);
+
+ assertEquals(5, mService.mAlarmStore.size());
+
+ final Intent packageReplacedIntent = new Intent(Intent.ACTION_PACKAGE_ADDED)
+ .setData(Uri.fromParts("package", TEST_CALLING_PACKAGE, null))
+ .putExtra(Intent.EXTRA_UID, TEST_CALLING_UID)
+ .putExtra(Intent.EXTRA_REPLACING, true);
+
+ mockUseExactAlarmState(false);
+ mockScheduleExactAlarmState(true, false, MODE_ALLOWED);
+ mPackageChangesReceiver.onReceive(mMockContext, packageReplacedIntent);
+ assertAndHandleMessageSync(CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE);
+
+ // user permission is granted, no alarms should be removed
+ assertEquals(5, mService.mAlarmStore.size());
+
+ mockUseExactAlarmState(true);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
+ mPackageChangesReceiver.onReceive(mMockContext, packageReplacedIntent);
+ assertAndHandleMessageSync(CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE);
+
+ // policy permission is granted, no alarms should be removed
+ assertEquals(5, mService.mAlarmStore.size());
+
+ mockUseExactAlarmState(false);
+ mockScheduleExactAlarmState(true, false, MODE_ERRORED);
+ mPackageChangesReceiver.onReceive(mMockContext, packageReplacedIntent);
+ assertAndHandleMessageSync(CHECK_EXACT_ALARM_PERMISSION_ON_UPDATE);
+
+ // no permission is granted, exact alarms should be removed
+ assertEquals(3, mService.mAlarmStore.size());
+
+ List<Alarm> remaining = mService.mAlarmStore.asList();
+ assertTrue("Inexact alarm removed", remaining.removeIf(a -> a.matches(inexactAlarm, null)));
+
+ assertEquals(2, remaining.size());
+ assertTrue("Alarms from other package removed",
+ remaining.removeIf(a -> a.matches(otherPackageExactAlarm, null)
+ || a.matches(otherPackageInexactAlarm, null)));
+
+ assertEquals(0, remaining.size());
+ }
+
+ @Test
public void alarmScheduledAtomPushed() {
for (int i = 0; i < 10; i++) {
final PendingIntent pi = getNewMockPendingIntent();
@@ -3187,6 +3248,28 @@ public class AlarmManagerServiceTest {
bOptions.getTemporaryAppAllowlistReasonCode());
}
+ @Test
+ public void hasUseExactAlarmPermission() {
+ mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, true);
+
+ mockUseExactAlarmState(true);
+ assertTrue(mService.hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID));
+
+ mockUseExactAlarmState(false);
+ assertFalse(mService.hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID));
+ }
+
+ @Test
+ public void hasUseExactAlarmPermissionChangeDisabled() {
+ mockChangeEnabled(AlarmManager.ENABLE_USE_EXACT_ALARM, false);
+
+ mockUseExactAlarmState(true);
+ assertFalse(mService.hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID));
+
+ mockUseExactAlarmState(false);
+ assertFalse(mService.hasUseExactAlarmInternal(TEST_CALLING_PACKAGE, TEST_CALLING_UID));
+ }
+
@After
public void tearDown() {
if (mMockingSession != null) {
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
index 47d4c8d9af46..32a87b62aeab 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BackgroundRestrictionTest.java
@@ -579,6 +579,7 @@ public final class BackgroundRestrictionTest {
DeviceConfigSession<Boolean> bgPromptFgsWithNotiToBgRestricted = null;
DeviceConfigSession<Long> bgNotificationMinInterval = null;
DeviceConfigSession<Integer> bgBatteryExemptionTypes = null;
+ DeviceConfigSession<Boolean> bgCurrentDrainDecoupleThresholds = null;
mBgRestrictionController.addAppBackgroundRestrictionListener(listener);
@@ -648,6 +649,13 @@ public final class BackgroundRestrictionTest {
R.integer.config_bg_current_drain_exempted_types));
bgBatteryExemptionTypes.set(0);
+ bgCurrentDrainDecoupleThresholds = new DeviceConfigSession<>(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLDS,
+ DeviceConfig::getBoolean,
+ AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLD);
+ bgCurrentDrainDecoupleThresholds.set(true);
+
mCurrentTimeMillis = 10_000L;
doReturn(mCurrentTimeMillis - windowMs).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis).when(stats).getStatsEndTimestamp();
@@ -785,6 +793,11 @@ public final class BackgroundRestrictionTest {
anyInt(), anyInt());
});
+ // Pretend we have the standby buckets set above.
+ doReturn(STANDBY_BUCKET_RESTRICTED)
+ .when(mAppStandbyInternal)
+ .getAppStandbyBucket(eq(testPkgName), eq(testUser), anyLong(), anyBoolean());
+
// Sleep a while and set a higher drain
Thread.sleep(windowMs);
clearInvocations(mInjector.getAppStandbyInternal());
@@ -921,6 +934,11 @@ public final class BackgroundRestrictionTest {
// Expected.
}
+ // Reset the standby bucket.
+ doReturn(STANDBY_BUCKET_RARE)
+ .when(mAppStandbyInternal)
+ .getAppStandbyBucket(eq(testPkgName), eq(testUser), anyLong(), anyBoolean());
+
// Turn OFF the FAS.
listener.mLatchHolder[0] = new CountDownLatch(1);
clearInvocations(mInjector.getAppStandbyInternal());
@@ -930,6 +948,99 @@ public final class BackgroundRestrictionTest {
// It'll go back to restricted bucket because it used to behave poorly.
listener.verify(timeout, testUid, testPkgName, RESTRICTION_LEVEL_RESTRICTED_BUCKET);
verifyRestrictionLevel(RESTRICTION_LEVEL_RESTRICTED_BUCKET, testPkgName, testUid);
+
+ clearInvocations(mInjector.getAppStandbyInternal());
+ // Trigger user interaction.
+ runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
+ new double[]{restrictBucketThresholdMah - 1, 0},
+ new double[]{0, restrictBucketThresholdMah - 1}, zeros, zeros,
+ () -> {
+ doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
+ doReturn(mCurrentTimeMillis + windowMs)
+ .when(stats).getStatsEndTimestamp();
+ mCurrentTimeMillis += windowMs + 1;
+ mIdleStateListener.onUserInteractionStarted(testPkgName, testUser);
+ waitForIdleHandler(mBgRestrictionController.getBackgroundHandler());
+ // It should have been back to normal.
+ listener.verify(timeout, testUid, testPkgName,
+ RESTRICTION_LEVEL_ADAPTIVE_BUCKET);
+ verify(mInjector.getAppStandbyInternal(), atLeast(1)).maybeUnrestrictApp(
+ eq(testPkgName),
+ eq(testUser),
+ eq(REASON_MAIN_USAGE),
+ eq(REASON_SUB_USAGE_USER_INTERACTION),
+ eq(REASON_MAIN_USAGE),
+ eq(REASON_SUB_USAGE_USER_INTERACTION));
+ });
+
+ bgCurrentDrainDecoupleThresholds.set(true);
+ clearInvocations(mInjector.getAppStandbyInternal());
+
+ // Go to the threshold right away.
+ runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
+ new double[]{0, restrictBucketThresholdMah - 1},
+ new double[]{bgRestrictedThresholdMah + 1, 0}, zeros, zeros,
+ () -> {
+ doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
+ doReturn(mCurrentTimeMillis + windowMs)
+ .when(stats).getStatsEndTimestamp();
+ mCurrentTimeMillis += windowMs + 1;
+ // We won't change restriction level automatically because it needs
+ // user consent.
+ try {
+ listener.verify(timeout, testUid, testPkgName,
+ RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
+ fail("There shouldn't be level change event like this");
+ } catch (Exception e) {
+ // Expected.
+ }
+ verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket(
+ eq(testPkgName),
+ eq(STANDBY_BUCKET_RARE),
+ eq(testUser),
+ anyInt(), anyInt());
+ // We should have requested to goto background restricted level.
+ verify(mBgRestrictionController, times(1)).handleRequestBgRestricted(
+ eq(testPkgName),
+ eq(testUid));
+ // Verify we have the notification posted now because its FGS is invisible.
+ checkNotificationShown(new String[] {testPkgName}, atLeast(1), true);
+ });
+
+ bgCurrentDrainDecoupleThresholds.set(false);
+ clearInvocations(mInjector.getAppStandbyInternal());
+ clearInvocations(mBgRestrictionController);
+
+ // Go to the threshold right away, but this time, it shouldn't even request to goto
+ // bg restricted level because it requires to be in restricted bucket before that.
+ runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
+ new double[]{0, restrictBucketThresholdMah - 1},
+ new double[]{bgRestrictedThresholdMah + 1, 0}, zeros, zeros,
+ () -> {
+ doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
+ doReturn(mCurrentTimeMillis + windowMs)
+ .when(stats).getStatsEndTimestamp();
+ mCurrentTimeMillis += windowMs + 1;
+ // We won't change restriction level automatically because it needs
+ // user consent.
+ try {
+ listener.verify(timeout, testUid, testPkgName,
+ RESTRICTION_LEVEL_BACKGROUND_RESTRICTED);
+ fail("There shouldn't be level change event like this");
+ } catch (Exception e) {
+ // Expected.
+ }
+ verify(mInjector.getAppStandbyInternal(), never()).setAppStandbyBucket(
+ eq(testPkgName),
+ eq(STANDBY_BUCKET_RARE),
+ eq(testUser),
+ anyInt(), anyInt());
+ // We should NOT have requested to goto background restricted level.
+ verify(mBgRestrictionController, never()).handleRequestBgRestricted(
+ eq(testPkgName),
+ eq(testUid));
+ });
+
} finally {
closeIfNotNull(bgCurrentDrainMonitor);
closeIfNotNull(bgCurrentDrainWindow);
@@ -938,6 +1049,7 @@ public final class BackgroundRestrictionTest {
closeIfNotNull(bgPromptFgsWithNotiToBgRestricted);
closeIfNotNull(bgNotificationMinInterval);
closeIfNotNull(bgBatteryExemptionTypes);
+ closeIfNotNull(bgCurrentDrainDecoupleThresholds);
}
}
@@ -1441,6 +1553,7 @@ public final class BackgroundRestrictionTest {
DeviceConfigSession<Boolean> bgPermissionMonitorEnabled = null;
DeviceConfigSession<String> bgPermissionsInMonitor = null;
DeviceConfigSession<Boolean> bgCurrentDrainHighThresholdByBgLocation = null;
+ DeviceConfigSession<Boolean> bgCurrentDrainDecoupleThresholds = null;
mBgRestrictionController.addAppBackgroundRestrictionListener(listener);
@@ -1572,6 +1685,13 @@ public final class BackgroundRestrictionTest {
R.bool.config_bg_current_drain_high_threshold_by_bg_location));
bgCurrentDrainHighThresholdByBgLocation.set(true);
+ bgCurrentDrainDecoupleThresholds = new DeviceConfigSession<>(
+ DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLDS,
+ DeviceConfig::getBoolean,
+ AppBatteryPolicy.DEFAULT_BG_CURRENT_DRAIN_DECOUPLE_THRESHOLD);
+ bgCurrentDrainDecoupleThresholds.set(true);
+
mCurrentTimeMillis = 10_000L;
doReturn(mCurrentTimeMillis - windowMs).when(stats).getStatsStartTimestamp();
doReturn(mCurrentTimeMillis).when(stats).getStatsEndTimestamp();
@@ -1990,6 +2110,7 @@ public final class BackgroundRestrictionTest {
closeIfNotNull(bgPermissionMonitorEnabled);
closeIfNotNull(bgPermissionsInMonitor);
closeIfNotNull(bgCurrentDrainHighThresholdByBgLocation);
+ closeIfNotNull(bgCurrentDrainDecoupleThresholds);
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java
index 04fe777cd909..b354c7b3d1f3 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobConcurrencyManagerTest.java
@@ -116,14 +116,14 @@ public final class JobConcurrencyManagerTest {
assertFalse(mJobConcurrencyManager.isPkgConcurrencyLimitedLocked(topJob));
// Pending jobs shouldn't affect TOP job's status.
- for (int i = 1; i <= JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) {
+ for (int i = 1; i <= JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i);
mPendingJobQueue.add(job);
}
assertFalse(mJobConcurrencyManager.isPkgConcurrencyLimitedLocked(topJob));
// Already running jobs shouldn't affect TOP job's status.
- for (int i = 1; i <= JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) {
+ for (int i = 1; i <= JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE, i);
mJobConcurrencyManager.addRunningJobForTesting(job);
}
@@ -183,9 +183,9 @@ public final class JobConcurrencyManagerTest {
spyOn(testEj);
doReturn(true).when(testEj).shouldTreatAsExpeditedJob();
- setConcurrencyConfig(JobSchedulerService.MAX_JOB_CONTEXTS_COUNT);
+ setConcurrencyConfig(JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT);
- for (int i = 0; i < JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
final JobStatus job = createJob(mDefaultUserId * UserHandle.PER_USER_RANGE + i, i + 1);
mPendingJobQueue.add(job);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index 1af6fb7a4027..0567f58b1bbe 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -203,6 +203,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
val domainVerificationManagerInternal: DomainVerificationManagerInternal = mock()
val handler = TestHandler(null)
val defaultAppProvider: DefaultAppProvider = mock()
+ val backgroundHandler = TestHandler(null)
}
companion object {
@@ -286,6 +287,7 @@ class MockSystem(withSession: (StaticMockitoSessionBuilder) -> Unit = {}) {
.thenReturn(mocks.domainVerificationManagerInternal)
whenever(mocks.injector.handler) { mocks.handler }
whenever(mocks.injector.defaultAppProvider) { mocks.defaultAppProvider }
+ whenever(mocks.injector.backgroundHandler) { mocks.backgroundHandler }
wheneverStatic { SystemConfig.getInstance() }.thenReturn(mocks.systemConfig)
whenever(mocks.systemConfig.availableFeatures).thenReturn(DEFAULT_AVAILABLE_FEATURES_MAP)
whenever(mocks.systemConfig.sharedLibraries).thenReturn(DEFAULT_SHARED_LIBRARIES_LIST)
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
index 4818573e9ae5..9774af31950a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/SuspendPackageHelperTest.kt
@@ -17,7 +17,6 @@
package com.android.server.pm
import android.content.Intent
-import android.content.pm.PackageManagerInternal
import android.content.pm.SuspendDialogInfo
import android.os.Binder
import android.os.Build
@@ -27,6 +26,7 @@ import android.os.UserHandle
import android.os.UserManager
import android.util.ArrayMap
import android.util.SparseArray
+import com.android.server.pm.KnownPackages
import com.android.server.pm.pkg.PackageStateInternal
import com.android.server.testutils.TestHandler
import com.android.server.testutils.any
@@ -484,14 +484,14 @@ class SuspendPackageHelperTest {
Mockito.doReturn(DIALER_PACKAGE).`when`(defaultAppProvider)
.getDefaultDialer(eq(TEST_USER_ID))
Mockito.doReturn(arrayOf(INSTALLER_PACKAGE)).`when`(pms).getKnownPackageNamesInternal(
- any(), eq(PackageManagerInternal.PACKAGE_INSTALLER), eq(TEST_USER_ID))
+ any(), eq(KnownPackages.PACKAGE_INSTALLER), eq(TEST_USER_ID))
Mockito.doReturn(arrayOf(UNINSTALLER_PACKAGE)).`when`(pms).getKnownPackageNamesInternal(
- any(), eq(PackageManagerInternal.PACKAGE_UNINSTALLER), eq(TEST_USER_ID))
+ any(), eq(KnownPackages.PACKAGE_UNINSTALLER), eq(TEST_USER_ID))
Mockito.doReturn(arrayOf(VERIFIER_PACKAGE)).`when`(pms).getKnownPackageNamesInternal(
- any(), eq(PackageManagerInternal.PACKAGE_VERIFIER), eq(TEST_USER_ID))
+ any(), eq(KnownPackages.PACKAGE_VERIFIER), eq(TEST_USER_ID))
Mockito.doReturn(arrayOf(PERMISSION_CONTROLLER_PACKAGE)).`when`(pms)
.getKnownPackageNamesInternal(any(),
- eq(PackageManagerInternal.PACKAGE_PERMISSION_CONTROLLER), eq(TEST_USER_ID))
+ eq(KnownPackages.PACKAGE_PERMISSION_CONTROLLER), eq(TEST_USER_ID))
}
private fun createPackageManagerService(vararg stageExistingPackages: String):
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index 7b921ababf36..c96b4d66f293 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -40,7 +40,8 @@ import android.app.admin.DevicePolicyManager;
import android.companion.AssociationInfo;
import android.companion.virtual.IVirtualDeviceActivityListener;
import android.companion.virtual.VirtualDeviceParams;
-import android.companion.virtual.audio.IAudioSessionCallback;
+import android.companion.virtual.audio.IAudioConfigChangedCallback;
+import android.companion.virtual.audio.IAudioRoutingCallback;
import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Point;
@@ -115,7 +116,9 @@ public class VirtualDeviceManagerServiceTest {
IThermalService mIThermalServiceMock;
private PowerManager mPowerManager;
@Mock
- private IAudioSessionCallback mCallback;
+ private IAudioRoutingCallback mRoutingCallback;
+ @Mock
+ private IAudioConfigChangedCallback mConfigChangedCallback;
@Before
public void setUp() {
@@ -258,7 +261,8 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onAudioSessionStarting_noDisplay_failsSecurityException() {
assertThrows(SecurityException.class,
- () -> mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mCallback));
+ () -> mDeviceImpl.onAudioSessionStarting(
+ DISPLAY_ID, mRoutingCallback, mConfigChangedCallback));
}
@Test
@@ -300,7 +304,8 @@ public class VirtualDeviceManagerServiceTest {
doCallRealMethod().when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.CREATE_VIRTUAL_DEVICE), anyString());
assertThrows(SecurityException.class,
- () -> mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mCallback));
+ () -> mDeviceImpl.onAudioSessionStarting(
+ DISPLAY_ID, mRoutingCallback, mConfigChangedCallback));
}
@Test
@@ -347,7 +352,7 @@ public class VirtualDeviceManagerServiceTest {
public void onAudioSessionStarting_hasVirtualAudioController() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
- mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mCallback);
+ mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
assertThat(mDeviceImpl.getVirtualAudioControllerForTesting()).isNotNull();
}
@@ -355,7 +360,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void onAudioSessionEnded_noVirtualAudioController() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
- mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mCallback);
+ mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
mDeviceImpl.onAudioSessionEnded();
@@ -365,7 +370,7 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void close_cleanVirtualAudioController() {
mDeviceImpl.onVirtualDisplayCreatedLocked(DISPLAY_ID);
- mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mCallback);
+ mDeviceImpl.onAudioSessionStarting(DISPLAY_ID, mRoutingCallback, mConfigChangedCallback);
mDeviceImpl.close();
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
index f0c907d49a46..75faf4554147 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/audio/VirtualAudioControllerTest.java
@@ -26,7 +26,8 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import android.companion.virtual.VirtualDeviceParams;
-import android.companion.virtual.audio.IAudioSessionCallback;
+import android.companion.virtual.audio.IAudioConfigChangedCallback;
+import android.companion.virtual.audio.IAudioRoutingCallback;
import android.content.Context;
import android.content.ContextWrapper;
import android.media.AudioPlaybackConfiguration;
@@ -60,7 +61,10 @@ public class VirtualAudioControllerTest {
private Context mContext;
private VirtualAudioController mVirtualAudioController;
private GenericWindowPolicyController mGenericWindowPolicyController;
- @Mock IAudioSessionCallback mCallback;
+ @Mock
+ private IAudioRoutingCallback mRoutingCallback;
+ @Mock
+ private IAudioConfigChangedCallback mConfigChangedCallback;
@Before
public void setUp() {
@@ -82,42 +86,46 @@ public class VirtualAudioControllerTest {
public void startListening_receivesCallback() throws RemoteException {
ArraySet<Integer> runningUids = new ArraySet<>();
runningUids.add(APP1_UID);
- int[] appUids = new int[] {APP1_UID};
+ int[] appUids = new int[]{APP1_UID};
- mVirtualAudioController.startListening(mGenericWindowPolicyController, mCallback);
+ mVirtualAudioController.startListening(
+ mGenericWindowPolicyController, mRoutingCallback, mConfigChangedCallback);
mGenericWindowPolicyController.onRunningAppsChanged(runningUids);
- verify(mCallback).onAppsNeedingAudioRoutingChanged(appUids);
+ verify(mRoutingCallback).onAppsNeedingAudioRoutingChanged(appUids);
}
@Test
public void stopListening_removesCallback() throws RemoteException {
ArraySet<Integer> runningUids = new ArraySet<>();
runningUids.add(APP1_UID);
- int[] appUids = new int[] {APP1_UID};
- mVirtualAudioController.startListening(mGenericWindowPolicyController, mCallback);
+ int[] appUids = new int[]{APP1_UID};
+ mVirtualAudioController.startListening(
+ mGenericWindowPolicyController, mRoutingCallback, mConfigChangedCallback);
mVirtualAudioController.stopListening();
mGenericWindowPolicyController.onRunningAppsChanged(runningUids);
- verify(mCallback, never()).onAppsNeedingAudioRoutingChanged(appUids);
+ verify(mRoutingCallback, never()).onAppsNeedingAudioRoutingChanged(appUids);
}
@Test
public void onRunningAppsChanged_notifiesAudioRoutingModified() throws RemoteException {
- mVirtualAudioController.startListening(mGenericWindowPolicyController, mCallback);
+ mVirtualAudioController.startListening(
+ mGenericWindowPolicyController, mRoutingCallback, mConfigChangedCallback);
ArraySet<Integer> runningUids = new ArraySet<>();
runningUids.add(APP1_UID);
mVirtualAudioController.onRunningAppsChanged(runningUids);
- int[] appUids = new int[] {APP1_UID};
- verify(mCallback).onAppsNeedingAudioRoutingChanged(appUids);
+ int[] appUids = new int[]{APP1_UID};
+ verify(mRoutingCallback).onAppsNeedingAudioRoutingChanged(appUids);
}
@Test
public void onRunningAppsChanged_audioIsPlaying_doesNothing() throws RemoteException {
- mVirtualAudioController.startListening(mGenericWindowPolicyController, mCallback);
+ mVirtualAudioController.startListening(
+ mGenericWindowPolicyController, mRoutingCallback, mConfigChangedCallback);
mVirtualAudioController.addPlayingAppsForTesting(APP2_UID);
ArraySet<Integer> runningUids = new ArraySet<>();
@@ -125,7 +133,7 @@ public class VirtualAudioControllerTest {
mVirtualAudioController.onRunningAppsChanged(runningUids);
int[] appUids = new int[]{APP1_UID};
- verify(mCallback, never()).onAppsNeedingAudioRoutingChanged(appUids);
+ verify(mRoutingCallback, never()).onAppsNeedingAudioRoutingChanged(appUids);
}
@Test
@@ -145,7 +153,8 @@ public class VirtualAudioControllerTest {
@Test
public void onPlaybackConfigChanged_sendsCallback() throws RemoteException {
- mVirtualAudioController.startListening(mGenericWindowPolicyController, mCallback);
+ mVirtualAudioController.startListening(
+ mGenericWindowPolicyController, mRoutingCallback, mConfigChangedCallback);
ArraySet<Integer> runningUids = new ArraySet<>();
runningUids.add(APP1_UID);
mVirtualAudioController.onRunningAppsChanged(runningUids);
@@ -153,12 +162,13 @@ public class VirtualAudioControllerTest {
mVirtualAudioController.onPlaybackConfigChanged(configs);
- verify(mCallback).onPlaybackConfigChanged(configs);
+ verify(mConfigChangedCallback).onPlaybackConfigChanged(configs);
}
@Test
public void onRecordingConfigChanged_sendsCallback() throws RemoteException {
- mVirtualAudioController.startListening(mGenericWindowPolicyController, mCallback);
+ mVirtualAudioController.startListening(
+ mGenericWindowPolicyController, mRoutingCallback, mConfigChangedCallback);
ArraySet<Integer> runningUids = new ArraySet<>();
runningUids.add(APP1_UID);
mVirtualAudioController.onRunningAppsChanged(runningUids);
@@ -166,7 +176,7 @@ public class VirtualAudioControllerTest {
mVirtualAudioController.onRecordingConfigChanged(configs);
- verify(mCallback).onRecordingConfigChanged(configs);
+ verify(mConfigChangedCallback).onRecordingConfigChanged(configs);
}
private List<AudioPlaybackConfiguration> createPlaybackConfigurations(
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 197c21fad74a..ef7aaca203f7 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -48,6 +48,9 @@ import static android.app.admin.DevicePolicyManager.WIFI_SECURITY_PERSONAL;
import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
import static android.app.admin.PasswordMetrics.computeForPasswordOrPin;
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
+import static android.location.LocationManager.FUSED_PROVIDER;
+import static android.location.LocationManager.GPS_PROVIDER;
+import static android.location.LocationManager.NETWORK_PROVIDER;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_DEFAULT;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE_NO_FALLBACK;
@@ -8462,34 +8465,44 @@ public class DevicePolicyManagerTest extends DpmTestBase {
@Test
public void testSendLostModeLocationUpdate_asDeviceOwner() throws Exception {
- final String TEST_PROVIDER = "network";
mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE);
setDeviceOwner();
- when(getServices().locationManager.getAllProviders()).thenReturn(List.of(TEST_PROVIDER));
- when(getServices().locationManager.isProviderEnabled(TEST_PROVIDER)).thenReturn(true);
+ when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(true);
dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {});
verify(getServices().locationManager, times(1)).getCurrentLocation(
- eq(TEST_PROVIDER), any(), eq(getServices().executor), any());
+ eq(FUSED_PROVIDER), any(), eq(getServices().executor), any());
}
@Test
public void testSendLostModeLocationUpdate_asProfileOwnerOfOrgOwnedDevice() throws Exception {
- final String TEST_PROVIDER = "network";
final int MANAGED_PROFILE_ADMIN_UID =
UserHandle.getUid(CALLER_USER_HANDLE, DpmMockContext.SYSTEM_UID);
mContext.binder.callingUid = MANAGED_PROFILE_ADMIN_UID;
mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE);
addManagedProfile(admin1, MANAGED_PROFILE_ADMIN_UID, admin1);
configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
- when(getServices().locationManager.getAllProviders()).thenReturn(List.of(TEST_PROVIDER));
- when(getServices().locationManager.isProviderEnabled(TEST_PROVIDER)).thenReturn(true);
+ when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(true);
dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {});
verify(getServices().locationManager, times(1)).getCurrentLocation(
- eq(TEST_PROVIDER), any(), eq(getServices().executor), any());
+ eq(FUSED_PROVIDER), any(), eq(getServices().executor), any());
+ }
+
+ @Test
+ public void testSendLostModeLocationUpdate_noProviderIsEnabled() throws Exception {
+ mContext.callerPermissions.add(permission.TRIGGER_LOST_MODE);
+ setDeviceOwner();
+ when(getServices().locationManager.isProviderEnabled(FUSED_PROVIDER)).thenReturn(false);
+ when(getServices().locationManager.isProviderEnabled(NETWORK_PROVIDER)).thenReturn(false);
+ when(getServices().locationManager.isProviderEnabled(GPS_PROVIDER)).thenReturn(false);
+
+ dpm.sendLostModeLocationUpdate(getServices().executor, /* empty callback */ result -> {});
+
+ verify(getServices().locationManager, never()).getCurrentLocation(
+ eq(FUSED_PROVIDER), any(), eq(getServices().executor), any());
}
private void setupVpnAuthorization(String userVpnPackage, int userVpnUid) {
diff --git a/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java b/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java
index bda7cf66f685..e886e7dc1d60 100644
--- a/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java
+++ b/services/tests/servicestests/src/com/android/server/job/BiasSchedulingTest.java
@@ -57,14 +57,14 @@ public class BiasSchedulingTest extends AndroidTestCase {
}
public void testLowerBiasJobPreempted() throws Exception {
- for (int i = 0; i < JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent)
.setBias(LOW_BIAS)
.setOverrideDeadline(0)
.build();
mJobScheduler.schedule(job);
}
- final int higherBiasJobId = 100 + JobSchedulerService.MAX_JOB_CONTEXTS_COUNT;
+ final int higherBiasJobId = 100 + JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT;
JobInfo jobHigher = new JobInfo.Builder(higherBiasJobId, sJobServiceComponent)
.setBias(HIGH_BIAS)
.setMinimumLatency(2000)
@@ -88,14 +88,14 @@ public class BiasSchedulingTest extends AndroidTestCase {
}
public void testHigherBiasJobNotPreempted() throws Exception {
- for (int i = 0; i < JobSchedulerService.MAX_JOB_CONTEXTS_COUNT; ++i) {
+ for (int i = 0; i < JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT; ++i) {
JobInfo job = new JobInfo.Builder(100 + i, sJobServiceComponent)
.setBias(HIGH_BIAS)
.setOverrideDeadline(0)
.build();
mJobScheduler.schedule(job);
}
- final int lowerBiasJobId = 100 + JobSchedulerService.MAX_JOB_CONTEXTS_COUNT;
+ final int lowerBiasJobId = 100 + JobConcurrencyManager.STANDARD_CONCURRENCY_LIMIT;
JobInfo jobLower = new JobInfo.Builder(lowerBiasJobId, sJobServiceComponent)
.setBias(LOW_BIAS)
.setMinimumLatency(2000)
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index 2b33088dd678..1877d45e5ce3 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -189,8 +189,8 @@ public class PackageManagerServiceTest {
@Test
public void testKnownPackageToString_shouldNotGetUnknown() {
final List<String> packageNames = new ArrayList<>();
- for (int i = 0; i <= PackageManagerInternal.LAST_KNOWN_PACKAGE; i++) {
- packageNames.add(PackageManagerInternal.knownPackageToString(i));
+ for (int i = 0; i <= KnownPackages.LAST_KNOWN_PACKAGE; i++) {
+ packageNames.add(KnownPackages.knownPackageToString(i));
}
assertWithMessage(
"The Ids of KnownPackage should be continuous and the string representation "
@@ -205,7 +205,7 @@ public class PackageManagerServiceTest {
"The last KnownPackage Id should be assigned to PackageManagerInternal"
+ ".LAST_KNOWN_PACKAGE.").that(
knownPackageIds.get(knownPackageIds.size() - 1)).isEqualTo(
- PackageManagerInternal.LAST_KNOWN_PACKAGE);
+ KnownPackages.LAST_KNOWN_PACKAGE);
}
@Test
@@ -470,7 +470,7 @@ public class PackageManagerServiceTest {
private List<Integer> getKnownPackageIdsList() throws IllegalAccessException {
final ArrayList<Integer> knownPackageIds = new ArrayList<>();
- final Field[] allFields = PackageManagerInternal.class.getDeclaredFields();
+ final Field[] allFields = KnownPackages.class.getDeclaredFields();
for (Field field : allFields) {
final int modifier = field.getModifiers();
if (isPublic(modifier) && isStatic(modifier) && isFinal(modifier)
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 17464a6551d4..fb4d84cc75f2 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -283,7 +283,7 @@ public class AppStandbyControllerTests {
}
@Override
- boolean hasScheduleExactAlarm(String packageName, int uid) {
+ boolean hasExactAlarmPermission(String packageName, int uid) {
return mClockApps.contains(Pair.create(packageName, uid));
}
diff --git a/services/translation/java/com/android/server/translation/TranslationManagerService.java b/services/translation/java/com/android/server/translation/TranslationManagerService.java
index 27b254a304ff..e8c989280a0e 100644
--- a/services/translation/java/com/android/server/translation/TranslationManagerService.java
+++ b/services/translation/java/com/android/server/translation/TranslationManagerService.java
@@ -225,12 +225,12 @@ public final class TranslationManagerService
@Override
public void registerUiTranslationStateCallback(IRemoteCallback callback, int userId) {
- TranslationManagerServiceImpl service;
synchronized (mLock) {
- service = getServiceForUserLocked(userId);
- }
- if (service != null) {
- service.registerUiTranslationStateCallback(callback, Binder.getCallingUid());
+ final TranslationManagerServiceImpl service = getServiceForUserLocked(userId);
+ if (service != null) {
+ service.registerUiTranslationStateCallbackLocked(callback,
+ Binder.getCallingUid());
+ }
}
}
@@ -297,7 +297,7 @@ public final class TranslationManagerService
/**
* Dump the service state into the given stream. You run "adb shell dumpsys translation".
- */
+ */
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) return;
diff --git a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
index 3833ceb3122e..d3a589668808 100644
--- a/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
+++ b/services/translation/java/com/android/server/translation/TranslationManagerServiceImpl.java
@@ -22,9 +22,13 @@ import static android.view.translation.UiTranslationManager.EXTRA_SOURCE_LOCALE;
import static android.view.translation.UiTranslationManager.EXTRA_STATE;
import static android.view.translation.UiTranslationManager.EXTRA_TARGET_LOCALE;
import static android.view.translation.UiTranslationManager.STATE_UI_TRANSLATION_FINISHED;
+import static android.view.translation.UiTranslationManager.STATE_UI_TRANSLATION_PAUSED;
+import static android.view.translation.UiTranslationManager.STATE_UI_TRANSLATION_RESUMED;
+import static android.view.translation.UiTranslationManager.STATE_UI_TRANSLATION_STARTED;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
@@ -38,7 +42,9 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.service.translation.TranslationServiceInfo;
import android.util.ArraySet;
+import android.util.Log;
import android.util.Slog;
+import android.util.SparseArray;
import android.view.autofill.AutofillId;
import android.view.inputmethod.InputMethodInfo;
import android.view.translation.ITranslationServiceCallback;
@@ -68,6 +74,8 @@ final class TranslationManagerServiceImpl extends
AbstractPerUserSystemService<TranslationManagerServiceImpl, TranslationManagerService> {
private static final String TAG = "TranslationManagerServiceImpl";
+ @SuppressLint("IsLoggableTagLength")
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@GuardedBy("mLock")
@Nullable
@@ -83,13 +91,19 @@ final class TranslationManagerServiceImpl extends
@GuardedBy("mLock")
private WeakReference<ActivityTokens> mLastActivityTokens;
- private ActivityTaskManagerInternal mActivityTaskManagerInternal;
+ private final ActivityTaskManagerInternal mActivityTaskManagerInternal;
private final TranslationServiceRemoteCallback mRemoteServiceCallback =
new TranslationServiceRemoteCallback();
private final RemoteCallbackList<IRemoteCallback> mTranslationCapabilityCallbacks =
new RemoteCallbackList<>();
- private final ArraySet<IBinder> mWaitingFinishedCallbackActivities = new ArraySet();
+ private final ArraySet<IBinder> mWaitingFinishedCallbackActivities = new ArraySet<>();
+
+ /**
+ * Key is translated activity uid, value is the specification and state for the translation.
+ */
+ @GuardedBy("mLock")
+ private final SparseArray<ActiveTranslation> mActiveTranslations = new SparseArray<>();
protected TranslationManagerServiceImpl(
@NonNull TranslationManagerService master,
@@ -231,6 +245,7 @@ final class TranslationManagerServiceImpl extends
if (state == STATE_UI_TRANSLATION_FINISHED) {
mWaitingFinishedCallbackActivities.add(token);
}
+
IBinder activityToken = taskTopActivityTokens.getActivityToken();
try {
taskTopActivityTokens.getApplicationThread().updateUiTranslationState(
@@ -243,9 +258,46 @@ final class TranslationManagerServiceImpl extends
ComponentName componentName = mActivityTaskManagerInternal.getActivityName(activityToken);
int translationActivityUid =
getActivityUidByComponentName(getContext(), componentName, getUserId());
+ String packageName = componentName.getPackageName();
if (state != STATE_UI_TRANSLATION_FINISHED) {
- invokeCallbacks(state, sourceSpec, targetSpec, componentName.getPackageName(),
+ invokeCallbacks(state, sourceSpec, targetSpec, packageName, translationActivityUid);
+ updateActiveTranslations(state, sourceSpec, targetSpec, packageName,
translationActivityUid);
+ } else {
+ if (mActiveTranslations.contains(translationActivityUid)) {
+ mActiveTranslations.delete(translationActivityUid);
+ } else {
+ Slog.w(TAG, "Finishing translation for activity with uid=" + translationActivityUid
+ + " but no active translation was found for it");
+ }
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void updateActiveTranslations(int state, TranslationSpec sourceSpec,
+ TranslationSpec targetSpec, String packageName, int translationActivityUid) {
+ // Keep track of active translations so that we can trigger callbacks that are
+ // registered after translation has started.
+ switch (state) {
+ case STATE_UI_TRANSLATION_STARTED: {
+ ActiveTranslation activeTranslation = new ActiveTranslation(sourceSpec,
+ targetSpec, packageName);
+ mActiveTranslations.put(translationActivityUid, activeTranslation);
+ break;
+ }
+ case STATE_UI_TRANSLATION_PAUSED:
+ case STATE_UI_TRANSLATION_RESUMED: {
+ ActiveTranslation activeTranslation = mActiveTranslations.get(
+ translationActivityUid);
+ if (activeTranslation != null) {
+ activeTranslation.isPaused = (state == STATE_UI_TRANSLATION_PAUSED);
+ } else {
+ Slog.w(TAG, "Pausing or resuming translation for activity with uid="
+ + translationActivityUid
+ + " but no active translation was found for it");
+ }
+ break;
+ }
}
}
@@ -289,49 +341,105 @@ final class TranslationManagerServiceImpl extends
private void invokeCallbacks(
int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, String packageName,
int translationActivityUid) {
- Bundle res = new Bundle();
- res.putInt(EXTRA_STATE, state);
+ Bundle result = createResultForCallback(state, sourceSpec, targetSpec, packageName);
+ if (mCallbacks.getRegisteredCallbackCount() == 0) {
+ return;
+ }
+ List<InputMethodInfo> enabledInputMethods = getEnabledInputMethods();
+ mCallbacks.broadcast((callback, uid) -> {
+ invokeCallback((int) uid, translationActivityUid, callback, result,
+ enabledInputMethods);
+ });
+ }
+
+ private List<InputMethodInfo> getEnabledInputMethods() {
+ return LocalServices.getService(InputMethodManagerInternal.class)
+ .getEnabledInputMethodListAsUser(mUserId);
+ }
+
+ private Bundle createResultForCallback(
+ int state, TranslationSpec sourceSpec, TranslationSpec targetSpec, String packageName) {
+ Bundle result = new Bundle();
+ result.putInt(EXTRA_STATE, state);
// TODO(177500482): Store the locale pair so it can be sent for RESUME events.
if (sourceSpec != null) {
- res.putSerializable(EXTRA_SOURCE_LOCALE, sourceSpec.getLocale());
- res.putSerializable(EXTRA_TARGET_LOCALE, targetSpec.getLocale());
+ result.putSerializable(EXTRA_SOURCE_LOCALE, sourceSpec.getLocale());
+ result.putSerializable(EXTRA_TARGET_LOCALE, targetSpec.getLocale());
}
- res.putString(EXTRA_PACKAGE_NAME, packageName);
- // TODO(177500482): Only support the *current* Input Method.
- List<InputMethodInfo> enabledInputMethods =
- LocalServices.getService(InputMethodManagerInternal.class)
- .getEnabledInputMethodListAsUser(mUserId);
- mCallbacks.broadcast((callback, uid) -> {
- if ((int) uid == translationActivityUid) {
- try {
- callback.sendResult(res);
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to invoke UiTranslationStateCallback: " + e);
- }
- return;
- }
- // Code here is non-optimal since it's temporary..
- boolean isIme = false;
- for (InputMethodInfo inputMethod : enabledInputMethods) {
- if ((int) uid == inputMethod.getServiceInfo().applicationInfo.uid) {
- isIme = true;
- }
- }
- // TODO(177500482): Invoke it for the application being translated too.
- if (!isIme) {
- return;
- }
+ result.putString(EXTRA_PACKAGE_NAME, packageName);
+ return result;
+ }
+
+ private void invokeCallback(
+ int callbackSourceUid, int translationActivityUid, IRemoteCallback callback,
+ Bundle result, List<InputMethodInfo> enabledInputMethods) {
+ if (callbackSourceUid == translationActivityUid) {
+ // Invoke callback for the application being translated.
try {
- callback.sendResult(res);
+ callback.sendResult(result);
} catch (RemoteException e) {
Slog.w(TAG, "Failed to invoke UiTranslationStateCallback: " + e);
}
- });
+ return;
+ }
+
+ // TODO(177500482): Only support the *current* Input Method.
+ // Code here is non-optimal since it's temporary..
+ boolean isIme = false;
+ for (InputMethodInfo inputMethod : enabledInputMethods) {
+ if (callbackSourceUid == inputMethod.getServiceInfo().applicationInfo.uid) {
+ isIme = true;
+ break;
+ }
+ }
+
+ if (!isIme) {
+ return;
+ }
+ try {
+ callback.sendResult(result);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to invoke UiTranslationStateCallback: " + e);
+ }
}
- public void registerUiTranslationStateCallback(IRemoteCallback callback, int sourceUid) {
+ @GuardedBy("mLock")
+ public void registerUiTranslationStateCallbackLocked(IRemoteCallback callback, int sourceUid) {
mCallbacks.register(callback, sourceUid);
- // TODO(177500482): trigger the callback here if we're already translating the UI.
+
+ if (mActiveTranslations.size() == 0) {
+ return;
+ }
+
+ // Trigger the callback for already active translations.
+ List<InputMethodInfo> enabledInputMethods = getEnabledInputMethods();
+ for (int i = 0; i < mActiveTranslations.size(); i++) {
+ int activeTranslationUid = mActiveTranslations.keyAt(i);
+ ActiveTranslation activeTranslation = mActiveTranslations.valueAt(i);
+ if (activeTranslation == null) {
+ continue;
+ }
+ String packageName = activeTranslation.packageName;
+ if (DEBUG) {
+ Slog.d(TAG, "Triggering callback for sourceUid=" + sourceUid
+ + " for translated activity with uid=" + activeTranslationUid
+ + "packageName=" + packageName + " isPaused=" + activeTranslation.isPaused);
+ }
+
+ Bundle startedResult = createResultForCallback(STATE_UI_TRANSLATION_STARTED,
+ activeTranslation.sourceSpec, activeTranslation.targetSpec,
+ packageName);
+ invokeCallback(sourceUid, activeTranslationUid, callback, startedResult,
+ enabledInputMethods);
+ if (activeTranslation.isPaused) {
+ // Also send event so callback owners know that translation was started then paused.
+ Bundle pausedResult = createResultForCallback(STATE_UI_TRANSLATION_PAUSED,
+ activeTranslation.sourceSpec, activeTranslation.targetSpec,
+ packageName);
+ invokeCallback(sourceUid, activeTranslationUid, callback, pausedResult,
+ enabledInputMethods);
+ }
+ }
}
public void unregisterUiTranslationStateCallback(IRemoteCallback callback) {
@@ -376,4 +484,18 @@ final class TranslationManagerServiceImpl extends
notifyClientsTranslationCapability(capability);
}
}
+
+ private static final class ActiveTranslation {
+ public final TranslationSpec sourceSpec;
+ public final TranslationSpec targetSpec;
+ public final String packageName;
+ public boolean isPaused = false;
+
+ private ActiveTranslation(TranslationSpec sourceSpec, TranslationSpec targetSpec,
+ String packageName) {
+ this.sourceSpec = sourceSpec;
+ this.targetSpec = targetSpec;
+ this.packageName = packageName;
+ }
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 8880bc492de7..8d7fab4d101f 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -4379,12 +4379,14 @@ public class CarrierConfigManager {
* The data stall recovery timers array in milliseconds, each element is the delay before
* performining next recovery action.
*
- * The default value of timers array are: [180000ms, 180000ms, 180000ms] (3 minutes)
+ * The default value of timers array are: [180000ms, 180000ms, 180000ms, 180000ms] (3 minutes)
* Array[0]: It's the timer between RECOVERY_ACTION GET_DATA_CALL_LIST and CLEANUP, if data
* stall symptom still occurred, it will perform next recovery action after 180000ms.
- * Array[1]: It's the timer between RECOVERY_ACTION CLEANUP and RADIO_RESTART, if data stall
+ * Array[1]: It's the timer between RECOVERY_ACTION CLEANUP and RE-REGISTER, if data stall
* symptom still occurred, it will perform next recovery action after 180000ms.
- * Array[2]: It's the timer between RECOVERY_ACTION RADIO_RESTART and RESET_MODEM, if data stall
+ * Array[2]: It's the timer between RECOVERY_ACTION RE-REGISTER and RADIO_RESTART, if data stall
+ * symptom still occurred, it will perform next recovery action after 180000ms.
+ * Array[3]: It's the timer between RECOVERY_ACTION RADIO_RESTART and RESET_MODEM, if data stall
* symptom still occurred, it will perform next recovery action after 180000ms.
*
* See the {@code RECOVERY_ACTION_*} constants in
@@ -4404,7 +4406,7 @@ public class CarrierConfigManager {
* RECOVERY_ACTION_CLEANUP to true, then it can be ignored to speed up the recovery
* action procedure.
*
- * The default value of boolean array are: [false, false, false, false]
+ * The default value of boolean array are: [false, false, true, false, false]
* Array[0]: When performing the recovery action, we can use this boolean value to determine
* if we need to perform RECOVERY_ACTION_GET_DATA_CALL_LIST.
* Array[1]: If data stall symptom still occurred, we can use this boolean value to determine
@@ -4414,8 +4416,10 @@ public class CarrierConfigManager {
* variable of action RECOVERY_ACTION_CLEANUP to true, then it can be ignored to speed up the
* recovery action procedure.
* Array[2]: If data stall symptom still occurred, we can use this boolean value to determine
- * if we need to perform RECOVERY_ACTION_RADIO_RESTART.
+ * if we need to perform RE-REGISTER.
* Array[3]: If data stall symptom still occurred, we can use this boolean value to determine
+ * if we need to perform RECOVERY_ACTION_RADIO_RESTART.
+ * Array[4]: If data stall symptom still occurred, we can use this boolean value to determine
* if we need to perform RECOVERY_ACTION_MODEM_RESET.
*
* See the {@code RECOVERY_ACTION_*} constants in
@@ -9159,9 +9163,9 @@ public class CarrierConfigManager {
SubscriptionManager.USAGE_SETTING_UNKNOWN);
// Default data stall recovery configurations.
sDefaults.putLongArray(KEY_DATA_STALL_RECOVERY_TIMERS_LONG_ARRAY,
- new long[] {180000, 180000, 180000});
+ new long[] {180000, 180000, 180000, 180000});
sDefaults.putBooleanArray(KEY_DATA_STALL_RECOVERY_SHOULD_SKIP_BOOL_ARRAY,
- new boolean[] {false, false, false, false});
+ new boolean[] {false, false, true, false, false});
}
/**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index fc9acb81d408..7c7bf0a21c3f 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -3216,6 +3216,11 @@ public class SubscriptionManager {
*
* @param subId sub id
* @param callbackIntent pending intent that will be sent after operation is done.
+ *
+ * to-be-deprecated this API is a duplicate of {@link EuiccManager#switchToSubscription(int,
+ * PendingIntent)} and does not support Multiple Enabled Profile(MEP). Apps should use
+ * {@link EuiccManager#switchToSubscription(int, PendingIntent)} or
+ * {@link EuiccManager#switchToSubscription(int, int, PendingIntent)} instead.
*/
@RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
public void switchToSubscription(int subId, @NonNull PendingIntent callbackIntent) {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index a425ee0ed969..d1319ac095ed 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -17,7 +17,6 @@
package com.android.server.wm.flicker.close
-import android.platform.test.annotations.Presubmit
import androidx.test.filters.FlakyTest
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -99,38 +98,6 @@ class CloseAppBackButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio
super.statusBarLayerRotatesScales()
}
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun launcherLayerReplacesApp() {
- // This test doesn't work in shell transitions because of b/206086894
- assumeFalse(isShellTransitionsEnabled)
- super.launcherLayerReplacesApp()
- }
-
- @FlakyTest(bugId = 214452854)
- @Test
- fun launcherLayerReplacesApp_shellTransit() {
- assumeTrue(isShellTransitionsEnabled)
- super.launcherLayerReplacesApp()
- }
-
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun entireScreenCovered() {
- // This test doesn't work in shell transitions because of b/206086894
- assumeFalse(isShellTransitionsEnabled)
- super.entireScreenCovered()
- }
-
- @FlakyTest(bugId = 214452854)
- @Test
- fun entireScreenCovered_shellTransit() {
- assumeTrue(isShellTransitionsEnabled)
- super.entireScreenCovered()
- }
-
companion object {
/**
* Creates the test configurations.
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index a0892612f4e4..f5fb10611d6b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -24,9 +24,6 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group4
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume.assumeFalse
-import org.junit.Assume.assumeTrue
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -83,18 +80,9 @@ class CloseAppHomeButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio
override fun navBarLayerRotatesAndScales() = super.navBarLayerRotatesAndScales()
/** {@inheritDoc} */
- @FlakyTest(bugId = 206753786)
+ @FlakyTest(bugId = 227430489)
@Test
override fun statusBarLayerRotatesScales() {
- // This test doesn't work in shell transitions because of b/206753786
- assumeFalse(isShellTransitionsEnabled)
- super.statusBarLayerRotatesScales()
- }
-
- @FlakyTest(bugId = 214452854)
- @Test
- fun statusBarLayerRotatesScales_shellTransit() {
- assumeTrue(isShellTransitionsEnabled)
super.statusBarLayerRotatesScales()
}
@@ -102,15 +90,6 @@ class CloseAppHomeButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio
@Presubmit
@Test
override fun launcherLayerReplacesApp() {
- // This test doesn't work in shell transitions because of b/206086894
- assumeFalse(isShellTransitionsEnabled)
- super.launcherLayerReplacesApp()
- }
-
- @FlakyTest(bugId = 214452854)
- @Test
- fun launcherLayerReplacesApp_shellTransit() {
- assumeTrue(isShellTransitionsEnabled)
super.launcherLayerReplacesApp()
}
@@ -118,15 +97,6 @@ class CloseAppHomeButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio
@Presubmit
@Test
override fun entireScreenCovered() {
- // This test doesn't work in shell transitions because of b/206086894
- assumeFalse(isShellTransitionsEnabled)
- super.entireScreenCovered()
- }
-
- @FlakyTest(bugId = 214452854)
- @Test
- fun entireScreenCovered_shellTransit() {
- assumeTrue(isShellTransitionsEnabled)
super.entireScreenCovered()
}
@@ -134,15 +104,6 @@ class CloseAppHomeButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio
@Presubmit
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
- // This test doesn't work in shell transitions because of b/215885246
- assumeFalse(isShellTransitionsEnabled)
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
- }
-
- @FlakyTest(bugId = 214452854)
- @Test
- fun visibleLayersShownMoreThanOneConsecutiveEntry_shellTransit() {
- assumeTrue(isShellTransitionsEnabled)
super.visibleLayersShownMoreThanOneConsecutiveEntry()
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index f8348203599f..2f6b8f008119 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -24,11 +24,8 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule.Companion.removeAllTasksButHome
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -59,11 +56,6 @@ import org.junit.runners.Parameterized
@Group1
open class OpenAppColdTest(testSpec: FlickerTestParameter)
: OpenAppFromLauncherTransition(testSpec) {
- @Before
- open fun before() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- }
-
/**
* Defines the transition used to run the test
*/
@@ -121,7 +113,7 @@ open class OpenAppColdTest(testSpec: FlickerTestParameter)
override fun navBarWindowIsVisible() = super.navBarWindowIsVisible()
/** {@inheritDoc} */
- @FlakyTest(bugId = 213852103)
+ @Presubmit
@Test
override fun entireScreenCovered() = super.entireScreenCovered()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest_ShellTransit.kt
deleted file mode 100644
index 0d2869cbd178..000000000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest_ShellTransit.kt
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.launch
-
-import androidx.test.filters.FlakyTest
-import android.platform.test.annotations.RequiresDevice
-import com.android.server.wm.flicker.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.annotation.Group1
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test cold launching an app from launcher
- *
- * To run this test: `atest FlickerTests:OpenAppColdTest`
- *
- * Actions:
- * Make sure no apps are running on the device
- * Launch an app [testApp] and wait animation to complete
- *
- * Notes:
- * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
- * are inherited [OpenAppTransition]
- * 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
- * including configuring navigation mode, initial orientation and ensuring no
- * apps are running before setup
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Group1
-@FlakyTest(bugId = 219688533)
-class OpenAppColdTest_ShellTransit(testSpec: FlickerTestParameter) : OpenAppColdTest(testSpec) {
- @Before
- override fun before() {
- Assume.assumeTrue(isShellTransitionsEnabled)
- }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 00fee82adf76..ee0f3d8cd945 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -135,7 +135,7 @@ open class OpenAppFromOverviewTest(testSpec: FlickerTestParameter)
override fun appLayerBecomesVisible() = super.appLayerBecomesVisible_warmStart()
/** {@inheritDoc} */
- @FlakyTest(bugId = 218624176)
+ @Presubmit
@Test
override fun appWindowBecomesVisible() = super.appWindowBecomesVisible_warmStart()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest_ShellTransit.kt
index 1c06495cf473..55e1e9ba8557 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest_ShellTransit.kt
@@ -54,7 +54,6 @@ import org.junit.runners.Parameterized
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Group1
-@FlakyTest(bugId = 219688533)
class OpenAppFromOverviewTest_ShellTransit(testSpec: FlickerTestParameter)
: OpenAppFromOverviewTest(testSpec) {
@Before
@@ -65,6 +64,11 @@ class OpenAppFromOverviewTest_ShellTransit(testSpec: FlickerTestParameter)
/** {@inheritDoc} */
@FlakyTest(bugId = 216266712)
@Test
+ override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
+
+ /** {@inheritDoc} */
+ @FlakyTest(bugId = 216266712)
+ @Test
override fun appWindowReplacesLauncherAsTopWindow() =
super.appWindowReplacesLauncherAsTopWindow()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index f700416e4269..fbd611a37d0a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -17,7 +17,6 @@
package com.android.server.wm.flicker.launch
import androidx.test.filters.FlakyTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.platform.test.annotations.RequiresDevice
import android.view.Surface
@@ -99,7 +98,7 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter)
* Checks that the nav bar starts the transition invisible, then becomes visible during
* the unlocking animation and remains visible at the end of the transition
*/
- @Postsubmit
+ @Presubmit
@Test
fun navBarWindowsVisibilityChanges() {
testSpec.assertWm {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index 2562098a10ff..48f6aeb4d824 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -24,10 +24,7 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -59,11 +56,6 @@ import org.junit.runners.Parameterized
@Group1
open class OpenAppWarmTest(testSpec: FlickerTestParameter)
: OpenAppFromLauncherTransition(testSpec) {
- @Before
- open fun before() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- }
-
/**
* Defines the transition used to run the test
*/
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest_ShellTransit.kt
deleted file mode 100644
index 3958dd2c89b4..000000000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest_ShellTransit.kt
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.launch
-
-import androidx.test.filters.FlakyTest
-import android.platform.test.annotations.RequiresDevice
-import com.android.server.wm.flicker.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.annotation.Group1
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test warm launching an app from launcher
- *
- * To run this test: `atest FlickerTests:OpenAppWarmTest`
- *
- * Actions:
- * Launch [testApp]
- * Press home
- * Relaunch an app [testApp] and wait animation to complete (only this action is traced)
- *
- * Notes:
- * 1. Some default assertions (e.g., nav bar, status bar and screen covered)
- * are inherited [OpenAppTransition]
- * 2. Part of the test setup occurs automatically via
- * [com.android.server.wm.flicker.TransitionRunnerWithRules],
- * including configuring navigation mode, initial orientation and ensuring no
- * apps are running before setup
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Group1
-@FlakyTest(bugId = 219688533)
-class OpenAppWarmTest_ShellTransit(testSpec: FlickerTestParameter)
- : OpenAppWarmTest(testSpec) {
- @Before
- override fun before() {
- Assume.assumeTrue(isShellTransitionsEnabled)
- }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index c89e6a44ab6c..1eb3d8da9f1e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -33,15 +33,12 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
import com.android.server.wm.flicker.helpers.WindowUtils
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.navBarLayerIsVisible
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsVisible
import com.android.server.wm.flicker.statusBarLayerIsVisible
import com.android.server.wm.flicker.statusBarWindowIsVisible
import com.android.server.wm.traces.common.FlickerComponentName
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -73,11 +70,6 @@ open class QuickSwitchBetweenTwoAppsBackTest(private val testSpec: FlickerTestPa
private val startDisplayBounds = WindowUtils.getDisplayBounds(testSpec.startRotation)
- @Before
- open fun before() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- }
-
@FlickerBuilderProvider
fun buildFlicker(): FlickerBuilder {
return FlickerBuilder(instrumentation).apply {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
deleted file mode 100644
index cffed81f6cb9..000000000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.quickswitch
-
-import androidx.test.filters.FlakyTest
-import android.platform.test.annotations.RequiresDevice
-import com.android.server.wm.flicker.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.annotation.Group1
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
-import org.junit.FixMethodOrder
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test quick switching back to previous app from last opened app
- *
- * To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsBackTest`
- *
- * Actions:
- * Launch an app [testApp1]
- * Launch another app [testApp2]
- * Swipe right from the bottom of the screen to quick switch back to the first app [testApp1]
- *
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Group1
-@FlakyTest(bugId = 219690120)
-class QuickSwitchBetweenTwoAppsBackTest_ShellTransit(testSpec: FlickerTestParameter)
- : QuickSwitchBetweenTwoAppsBackTest(testSpec) {
- @Before
- override fun before() {
- Assume.assumeTrue(isShellTransitionsEnabled)
- }
-}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index b449dd227ad3..5474a42ccf52 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -32,7 +32,6 @@ import com.android.server.wm.flicker.annotation.Group1
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.NonResizeableAppHelper
import com.android.server.wm.flicker.helpers.SimpleAppHelper
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.navBarLayerIsVisible
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsVisible
@@ -40,8 +39,6 @@ import com.android.server.wm.flicker.statusBarLayerIsVisible
import com.android.server.wm.flicker.statusBarWindowIsVisible
import com.android.server.wm.traces.common.FlickerComponentName
import com.android.server.wm.traces.common.Rect
-import org.junit.Assume
-import org.junit.Before
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -114,12 +111,6 @@ open class QuickSwitchBetweenTwoAppsForwardTest(private val testSpec: FlickerTes
}
}
- @Before
- open fun setup() {
- // This test doesn't work in shell transitions because of b/213867585
- Assume.assumeFalse(isShellTransitionsEnabled)
- }
-
/**
* Checks that the transition starts with [testApp1]'s windows filling/covering exactly the
* entirety of the display.
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestShellTransit.kt
deleted file mode 100644
index 49b973390e7c..000000000000
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTestShellTransit.kt
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm.flicker.quickswitch
-
-import android.platform.test.annotations.RequiresDevice
-import androidx.test.filters.FlakyTest
-import com.android.server.wm.flicker.FlickerParametersRunnerFactory
-import com.android.server.wm.flicker.FlickerTestParameter
-import com.android.server.wm.flicker.annotation.Group1
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
-import org.junit.Assume
-import org.junit.Before
-import org.junit.FixMethodOrder
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
-import org.junit.runners.Parameterized
-
-/**
- * Test quick switching back to previous app from last opened app
- *
- * To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsForwardTestShellTransit`
- *
- * Actions:
- * Launch an app [testApp1]
- * Launch another app [testApp2]
- * Swipe right from the bottom of the screen to quick switch back to the first app [testApp1]
- * Swipe left from the bottom of the screen to quick switch forward to the second app [testApp2]
- */
-@RequiresDevice
-@RunWith(Parameterized::class)
-@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-@Group1
-class QuickSwitchBetweenTwoAppsForwardTestShellTransit(private val testSpec: FlickerTestParameter)
- : QuickSwitchBetweenTwoAppsForwardTest(testSpec) {
-
- @Before
- override fun setup() {
- // This test class should be removed after b/213867585 is fixed.
- Assume.assumeTrue(isShellTransitionsEnabled)
- }
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun startsWithApp1WindowsCoverFullScreen() =
- super.startsWithApp1WindowsCoverFullScreen()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun startsWithApp1LayersCoverFullScreen() = super.startsWithApp1LayersCoverFullScreen()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun startsWithApp1WindowBeingOnTop() = super.startsWithApp1WindowBeingOnTop()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun endsWithApp2WindowsCoveringFullScreen() =
- super.endsWithApp2WindowsCoveringFullScreen()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun endsWithApp2LayersCoveringFullScreen() =
- super.endsWithApp2LayersCoveringFullScreen()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun endsWithApp2BeingOnTop() = super.endsWithApp2BeingOnTop()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun app2WindowBecomesAndStaysVisible() = super.app2WindowBecomesAndStaysVisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun app2LayerBecomesAndStaysVisible() = super.app2LayerBecomesAndStaysVisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun app1WindowBecomesAndStaysInvisible() = super.app1WindowBecomesAndStaysInvisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun app1LayerBecomesAndStaysInvisible() = super.app1LayerBecomesAndStaysInvisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun app2WindowIsVisibleOnceApp1WindowIsInvisible() =
- super.app2WindowIsVisibleOnceApp1WindowIsInvisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun app2LayerIsVisibleOnceApp1LayerIsInvisible() =
- super.app2LayerIsVisibleOnceApp1LayerIsInvisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun navBarLayerAlwaysIsVisible() = super.navBarLayerAlwaysIsVisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun navbarIsAlwaysInRightPosition() = super.navbarIsAlwaysInRightPosition()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @FlakyTest(bugId = 214452854)
- @Test
- override fun statusBarLayerIsAlwaysVisible() = super.statusBarLayerIsAlwaysVisible()
-} \ No newline at end of file