summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt78
-rw-r--r--core/api/system-current.txt8
-rw-r--r--core/java/android/app/admin/flags/flags.aconfig24
-rw-r--r--core/java/android/service/dreams/flags.aconfig10
-rw-r--r--core/java/android/window/SnapshotDrawerUtils.java106
-rw-r--r--core/java/android/window/StartingWindowInfo.java11
-rw-r--r--core/res/res/values/config.xml1
-rw-r--r--core/res/res/values/public-final.xml181
-rw-r--r--core/res/res/values/public-staging.xml115
-rw-r--r--core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java27
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java5
-rw-r--r--location/java/android/location/flags/location.aconfig7
-rw-r--r--packages/SettingsLib/res/values/strings.xml3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java9
-rw-r--r--packages/Shell/Android.bp3
-rw-r--r--packages/Shell/src/com/android/shell/BugreportProgressService.java61
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelTest.kt80
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt7
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt49
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt37
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java122
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt45
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java3
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelKosmos.kt30
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt2
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java41
-rw-r--r--services/core/java/com/android/server/am/UserController.java167
-rw-r--r--services/core/java/com/android/server/audio/AudioManagerShellCommand.java24
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssConfiguration.java2
-rw-r--r--services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java2
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java44
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java1
-rw-r--r--services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java17
-rw-r--r--services/core/java/com/android/server/wm/Task.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java4
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java41
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java39
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UserControllerTest.java94
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java84
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java55
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java38
-rw-r--r--tests/FlickerTests/IME/AndroidTestTemplate.xml2
-rw-r--r--tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt101
53 files changed, 1332 insertions, 562 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 2f2a7656e680..53cf7d59f974 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -451,12 +451,12 @@ package android {
field public static final int alertDialogTheme = 16843529; // 0x1010309
field public static final int alignmentMode = 16843642; // 0x101037a
field public static final int allContactsName = 16843468; // 0x10102cc
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int allow;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int allow = 16844430; // 0x101068e
field public static final int allowAudioPlaybackCapture = 16844289; // 0x1010601
field public static final int allowBackup = 16843392; // 0x1010280
field public static final int allowClearUserData = 16842757; // 0x1010005
field public static final int allowClickWhenDisabled = 16844312; // 0x1010618
- field @FlaggedApi("android.security.asm_restrictions_enabled") public static final int allowCrossUidActivitySwitchFromBelow;
+ field @FlaggedApi("android.security.asm_restrictions_enabled") public static final int allowCrossUidActivitySwitchFromBelow = 16844449; // 0x10106a1
field public static final int allowEmbedded = 16843765; // 0x10103f5
field public static final int allowGameAngleDriver = 16844376; // 0x1010658
field public static final int allowGameDownscaling = 16844377; // 0x1010659
@@ -511,7 +511,7 @@ package android {
field public static final int autoSizeTextType = 16844085; // 0x1010535
field public static final int autoStart = 16843445; // 0x10102b5
field @Deprecated public static final int autoText = 16843114; // 0x101016a
- field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int autoTransact;
+ field @FlaggedApi("android.nfc.nfc_read_polling_loop") public static final int autoTransact = 16844441; // 0x1010699
field public static final int autoUrlDetect = 16843404; // 0x101028c
field public static final int autoVerify = 16844014; // 0x10104ee
field public static final int autofillHints = 16844118; // 0x1010556
@@ -658,7 +658,7 @@ package android {
field public static final int contentInsetRight = 16843862; // 0x1010456
field public static final int contentInsetStart = 16843859; // 0x1010453
field public static final int contentInsetStartWithNavigation = 16844066; // 0x1010522
- field @FlaggedApi("android.view.flags.sensitive_content_app_protection_api") public static final int contentSensitivity;
+ field @FlaggedApi("android.view.flags.sensitive_content_app_protection_api") public static final int contentSensitivity = 16844446; // 0x101069e
field public static final int contextClickable = 16844007; // 0x10104e7
field public static final int contextDescription = 16844078; // 0x101052e
field public static final int contextPopupMenuStyle = 16844033; // 0x1010501
@@ -688,7 +688,7 @@ package android {
field public static final int debuggable = 16842767; // 0x101000f
field public static final int defaultFocusHighlightEnabled = 16844130; // 0x1010562
field public static final int defaultHeight = 16844021; // 0x10104f5
- field @FlaggedApi("android.content.res.default_locale") public static final int defaultLocale;
+ field @FlaggedApi("android.content.res.default_locale") public static final int defaultLocale = 16844424; // 0x1010688
field public static final int defaultToDeviceProtectedStorage = 16844036; // 0x1010504
field public static final int defaultValue = 16843245; // 0x10101ed
field public static final int defaultWidth = 16844020; // 0x10104f4
@@ -858,7 +858,7 @@ package android {
field public static final int format24Hour = 16843723; // 0x10103cb
field public static final int fraction = 16843992; // 0x10104d8
field public static final int fragment = 16843491; // 0x10102e3
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentAdvancedPattern;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentAdvancedPattern = 16844438; // 0x1010696
field public static final int fragmentAllowEnterTransitionOverlap = 16843976; // 0x10104c8
field public static final int fragmentAllowReturnTransitionOverlap = 16843977; // 0x10104c9
field public static final int fragmentCloseEnterAnimation = 16843495; // 0x10102e7
@@ -869,13 +869,13 @@ package android {
field public static final int fragmentFadeExitAnimation = 16843498; // 0x10102ea
field public static final int fragmentOpenEnterAnimation = 16843493; // 0x10102e5
field public static final int fragmentOpenExitAnimation = 16843494; // 0x10102e6
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentPattern;
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentPrefix;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentPattern = 16844437; // 0x1010695
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentPrefix = 16844436; // 0x1010694
field public static final int fragmentReenterTransition = 16843975; // 0x10104c7
field public static final int fragmentReturnTransition = 16843973; // 0x10104c5
field public static final int fragmentSharedElementEnterTransition = 16843972; // 0x10104c4
field public static final int fragmentSharedElementReturnTransition = 16843974; // 0x10104c6
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentSuffix;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int fragmentSuffix = 16844439; // 0x1010697
field public static final int freezesText = 16843116; // 0x101016c
field public static final int fromAlpha = 16843210; // 0x10101ca
field public static final int fromDegrees = 16843187; // 0x10101b3
@@ -1345,15 +1345,15 @@ package android {
field public static final int propertyYName = 16843893; // 0x1010475
field public static final int protectionLevel = 16842761; // 0x1010009
field public static final int publicKey = 16843686; // 0x10103a6
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int query;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int query = 16844431; // 0x101068f
field public static final int queryActionMsg = 16843227; // 0x10101db
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryAdvancedPattern;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryAdvancedPattern = 16844434; // 0x1010692
field public static final int queryAfterZeroResults = 16843394; // 0x1010282
field public static final int queryBackground = 16843911; // 0x1010487
field public static final int queryHint = 16843608; // 0x1010358
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryPattern;
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryPrefix;
- field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int querySuffix;
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryPattern = 16844433; // 0x1010691
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int queryPrefix = 16844432; // 0x1010690
+ field @FlaggedApi("android.content.pm.relative_reference_intent_filters") public static final int querySuffix = 16844435; // 0x1010693
field public static final int quickContactBadgeStyleSmallWindowLarge = 16843443; // 0x10102b3
field public static final int quickContactBadgeStyleSmallWindowMedium = 16843442; // 0x10102b2
field public static final int quickContactBadgeStyleSmallWindowSmall = 16843441; // 0x10102b1
@@ -1382,7 +1382,7 @@ package android {
field public static final int reqTouchScreen = 16843303; // 0x1010227
field public static final int requestLegacyExternalStorage = 16844291; // 0x1010603
field public static final int requestRawExternalStorageAccess = 16844357; // 0x1010645
- field @FlaggedApi("android.security.content_uri_permission_apis") public static final int requireContentUriPermissionFromCaller;
+ field @FlaggedApi("android.security.content_uri_permission_apis") public static final int requireContentUriPermissionFromCaller = 16844443; // 0x101069b
field public static final int requireDeviceScreenOn = 16844317; // 0x101061d
field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
@@ -1494,12 +1494,12 @@ package android {
field @Deprecated public static final int sharedUserLabel = 16843361; // 0x1010261
field public static final int sharedUserMaxSdkVersion = 16844365; // 0x101064d
field public static final int shell = 16844180; // 0x1010594
- field @FlaggedApi("com.android.text.flags.use_bounds_for_width") public static final int shiftDrawingOffsetForStartOverhang;
+ field @FlaggedApi("com.android.text.flags.use_bounds_for_width") public static final int shiftDrawingOffsetForStartOverhang = 16844450; // 0x10106a2
field public static final int shortcutDisabledMessage = 16844075; // 0x101052b
field public static final int shortcutId = 16844072; // 0x1010528
field public static final int shortcutLongLabel = 16844074; // 0x101052a
field public static final int shortcutShortLabel = 16844073; // 0x1010529
- field @FlaggedApi("android.nfc.nfc_observe_mode") public static final int shouldDefaultToObserveMode;
+ field @FlaggedApi("android.nfc.nfc_observe_mode") public static final int shouldDefaultToObserveMode = 16844448; // 0x10106a0
field public static final int shouldDisableView = 16843246; // 0x10101ee
field public static final int shouldUseDefaultUnfoldTransition = 16844364; // 0x101064c
field public static final int showAsAction = 16843481; // 0x10102d9
@@ -1610,7 +1610,7 @@ package android {
field public static final int supportedTypes = 16844369; // 0x1010651
field public static final int supportsAssist = 16844016; // 0x10104f0
field public static final int supportsBatteryGameMode = 16844374; // 0x1010656
- field @FlaggedApi("android.view.inputmethod.connectionless_handwriting") public static final int supportsConnectionlessStylusHandwriting;
+ field @FlaggedApi("android.view.inputmethod.connectionless_handwriting") public static final int supportsConnectionlessStylusHandwriting = 16844447; // 0x101069f
field public static final int supportsInlineSuggestions = 16844301; // 0x101060d
field public static final int supportsInlineSuggestionsWithTouchExploration = 16844397; // 0x101066d
field public static final int supportsLaunchVoiceAssistFromKeyguard = 16844017; // 0x10104f1
@@ -1631,7 +1631,7 @@ package android {
field public static final int switchTextOff = 16843628; // 0x101036c
field public static final int switchTextOn = 16843627; // 0x101036b
field public static final int syncable = 16842777; // 0x1010019
- field @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") public static final int systemUserOnly;
+ field @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") public static final int systemUserOnly = 16844429; // 0x101068d
field public static final int tabStripEnabled = 16843453; // 0x10102bd
field public static final int tabStripLeft = 16843451; // 0x10102bb
field public static final int tabStripRight = 16843452; // 0x10102bc
@@ -1808,12 +1808,12 @@ package android {
field public static final int updatePeriodMillis = 16843344; // 0x1010250
field public static final int use32bitAbi = 16844053; // 0x1010515
field public static final int useAppZygote = 16844183; // 0x1010597
- field @FlaggedApi("com.android.text.flags.use_bounds_for_width") public static final int useBoundsForWidth;
+ field @FlaggedApi("com.android.text.flags.use_bounds_for_width") public static final int useBoundsForWidth = 16844440; // 0x1010698
field public static final int useDefaultMargins = 16843641; // 0x1010379
field public static final int useEmbeddedDex = 16844190; // 0x101059e
field public static final int useIntrinsicSizeAsMinimum = 16843536; // 0x1010310
field public static final int useLevel = 16843167; // 0x101019f
- field @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public static final int useLocalePreferredLineHeightForMinimum;
+ field @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") public static final int useLocalePreferredLineHeightForMinimum = 16844445; // 0x101069d
field public static final int userVisible = 16843409; // 0x1010291
field public static final int usesCleartextTraffic = 16844012; // 0x10104ec
field public static final int usesPermissionFlags = 16844356; // 0x1010644
@@ -1892,7 +1892,7 @@ package android {
field public static final int windowFullscreen = 16843277; // 0x101020d
field public static final int windowHideAnimation = 16842935; // 0x10100b7
field public static final int windowIsFloating = 16842839; // 0x1010057
- field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final int windowIsFrameRatePowerSavingsBalanced;
+ field @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") public static final int windowIsFrameRatePowerSavingsBalanced = 16844451; // 0x10106a3
field public static final int windowIsTranslucent = 16842840; // 0x1010058
field public static final int windowLayoutAffinity = 16844313; // 0x1010619
field public static final int windowLayoutInDisplayCutoutMode = 16844166; // 0x1010586
@@ -1903,7 +1903,7 @@ package android {
field public static final int windowNoDisplay = 16843294; // 0x101021e
field public static final int windowNoMoveAnimation = 16844421; // 0x1010685
field public static final int windowNoTitle = 16842838; // 0x1010056
- field @FlaggedApi("com.android.window.flags.enforce_edge_to_edge") public static final int windowOptOutEdgeToEdgeEnforcement;
+ field @FlaggedApi("com.android.window.flags.enforce_edge_to_edge") public static final int windowOptOutEdgeToEdgeEnforcement = 16844442; // 0x101069a
field @Deprecated public static final int windowOverscan = 16843727; // 0x10103cf
field public static final int windowReenterTransition = 16843951; // 0x10104af
field public static final int windowReturnTransition = 16843950; // 0x10104ae
@@ -2015,19 +2015,19 @@ package android {
field public static final int system_control_highlight_light = 17170558; // 0x106007e
field public static final int system_control_normal_dark = 17170600; // 0x10600a8
field public static final int system_control_normal_light = 17170557; // 0x106007d
- field public static final int system_error_0;
- field public static final int system_error_10;
- field public static final int system_error_100;
- field public static final int system_error_1000;
- field public static final int system_error_200;
- field public static final int system_error_300;
- field public static final int system_error_400;
- field public static final int system_error_50;
- field public static final int system_error_500;
- field public static final int system_error_600;
- field public static final int system_error_700;
- field public static final int system_error_800;
- field public static final int system_error_900;
+ field public static final int system_error_0 = 17170629; // 0x10600c5
+ field public static final int system_error_10 = 17170630; // 0x10600c6
+ field public static final int system_error_100 = 17170632; // 0x10600c8
+ field public static final int system_error_1000 = 17170641; // 0x10600d1
+ field public static final int system_error_200 = 17170633; // 0x10600c9
+ field public static final int system_error_300 = 17170634; // 0x10600ca
+ field public static final int system_error_400 = 17170635; // 0x10600cb
+ field public static final int system_error_50 = 17170631; // 0x10600c7
+ field public static final int system_error_500 = 17170636; // 0x10600cc
+ field public static final int system_error_600 = 17170637; // 0x10600cd
+ field public static final int system_error_700 = 17170638; // 0x10600ce
+ field public static final int system_error_800 = 17170639; // 0x10600cf
+ field public static final int system_error_900 = 17170640; // 0x10600d0
field public static final int system_error_container_dark = 17170597; // 0x10600a5
field public static final int system_error_container_light = 17170554; // 0x106007a
field public static final int system_error_dark = 17170595; // 0x10600a3
@@ -2077,7 +2077,7 @@ package android {
field public static final int system_on_secondary_fixed_variant = 17170619; // 0x10600bb
field public static final int system_on_secondary_light = 17170533; // 0x1060065
field public static final int system_on_surface_dark = 17170584; // 0x1060098
- field public static final int system_on_surface_disabled;
+ field public static final int system_on_surface_disabled = 17170627; // 0x10600c3
field public static final int system_on_surface_light = 17170541; // 0x106006d
field public static final int system_on_surface_variant_dark = 17170593; // 0x10600a1
field public static final int system_on_surface_variant_light = 17170550; // 0x1060076
@@ -2088,7 +2088,7 @@ package android {
field public static final int system_on_tertiary_fixed_variant = 17170623; // 0x10600bf
field public static final int system_on_tertiary_light = 17170537; // 0x1060069
field public static final int system_outline_dark = 17170594; // 0x10600a2
- field public static final int system_outline_disabled;
+ field public static final int system_outline_disabled = 17170628; // 0x10600c4
field public static final int system_outline_light = 17170551; // 0x1060077
field public static final int system_outline_variant_dark = 17170625; // 0x10600c1
field public static final int system_outline_variant_light = 17170624; // 0x10600c0
@@ -2129,7 +2129,7 @@ package android {
field public static final int system_surface_dark = 17170583; // 0x1060097
field public static final int system_surface_dim_dark = 17170591; // 0x106009f
field public static final int system_surface_dim_light = 17170548; // 0x1060074
- field public static final int system_surface_disabled;
+ field public static final int system_surface_disabled = 17170626; // 0x10600c2
field public static final int system_surface_light = 17170540; // 0x106006c
field public static final int system_surface_variant_dark = 17170592; // 0x10600a0
field public static final int system_surface_variant_light = 17170549; // 0x1060075
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index e12da637c2eb..f10c0fc21455 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -437,10 +437,10 @@ package android {
public static final class R.attr {
field public static final int allowClearUserDataOnFailedRestore = 16844288; // 0x1010600
- field @FlaggedApi("android.content.res.manifest_flagging") public static final int featureFlag;
+ field @FlaggedApi("android.content.res.manifest_flagging") public static final int featureFlag = 16844428; // 0x101068c
field public static final int gameSessionService = 16844373; // 0x1010655
field public static final int hotwordDetectionService = 16844326; // 0x1010626
- field @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") public static final int isVirtualDeviceOnly;
+ field @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime") public static final int isVirtualDeviceOnly = 16844425; // 0x1010689
field public static final int isVrOnly = 16844152; // 0x1010578
field public static final int minExtensionVersion = 16844305; // 0x1010611
field public static final int playHomeTransitionSound = 16844358; // 0x1010646
@@ -492,9 +492,9 @@ package android {
field public static final int config_defaultCallScreening = 17039398; // 0x1040026
field public static final int config_defaultDialer = 17039395; // 0x1040023
field public static final int config_defaultNotes = 17039429; // 0x1040045
- field @FlaggedApi("android.permission.flags.retail_demo_role_enabled") public static final int config_defaultRetailDemo;
+ field @FlaggedApi("android.permission.flags.retail_demo_role_enabled") public static final int config_defaultRetailDemo = 17039432; // 0x1040048
field public static final int config_defaultSms = 17039396; // 0x1040024
- field @FlaggedApi("android.permission.flags.wallet_role_enabled") public static final int config_defaultWallet;
+ field @FlaggedApi("android.permission.flags.wallet_role_enabled") public static final int config_defaultWallet = 17039433; // 0x1040049
field public static final int config_devicePolicyManagement = 17039421; // 0x104003d
field public static final int config_feedbackIntentExtraKey = 17039391; // 0x104001f
field public static final int config_feedbackIntentNameKey = 17039392; // 0x1040020
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index 31c9a258da56..18914e120d52 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -275,13 +275,23 @@ flag {
}
flag {
- name: "headless_single_user_bad_device_admin_state_fix"
- namespace: "enterprise"
- description: "Fix the bad state in DPMS caused by an earlier bug related to the headless single user change"
- bug: "332477138"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
+ name: "headless_single_user_bad_device_admin_state_fix"
+ namespace: "enterprise"
+ description: "Fix the bad state in DPMS caused by an earlier bug related to the headless single user change"
+ bug: "332477138"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
+ name: "onboarding_bugreport_storage_bug_fix"
+ namespace: "enterprise"
+ description: "Add a separate storage limit for deferred bugreports"
+ bug: "330177040"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
flag {
diff --git a/core/java/android/service/dreams/flags.aconfig b/core/java/android/service/dreams/flags.aconfig
index f87cb85f94b7..a42eaff68917 100644
--- a/core/java/android/service/dreams/flags.aconfig
+++ b/core/java/android/service/dreams/flags.aconfig
@@ -29,6 +29,16 @@ flag {
}
flag {
+ name: "dismiss_dream_on_keyguard_dismiss"
+ namespace: "systemui"
+ description: "Dismisses the dream in the keyguard-going-away transition, preventing it from being visible"
+ bug: "333829441"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "dream_tracks_focus"
namespace: "communal"
description: "This flag enables the ability for dreams to track whether or not they have focus"
diff --git a/core/java/android/window/SnapshotDrawerUtils.java b/core/java/android/window/SnapshotDrawerUtils.java
index e5658e63f7ec..29bb32e6443f 100644
--- a/core/java/android/window/SnapshotDrawerUtils.java
+++ b/core/java/android/window/SnapshotDrawerUtils.java
@@ -52,11 +52,9 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.GraphicBuffer;
-import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
-import android.graphics.RectF;
import android.hardware.HardwareBuffer;
import android.os.IBinder;
import android.util.Log;
@@ -98,11 +96,6 @@ public class SnapshotDrawerUtils {
| FLAG_SECURE
| FLAG_DIM_BEHIND;
- private static final RectF sTmpSnapshotSize = new RectF();
- private static final RectF sTmpDstFrame = new RectF();
-
- private static final Matrix sSnapshotMatrix = new Matrix();
- private static final float[] sTmpFloat9 = new float[9];
private static final Paint sBackgroundPaint = new Paint();
/**
@@ -116,24 +109,27 @@ public class SnapshotDrawerUtils {
private final CharSequence mTitle;
private SystemBarBackgroundPainter mSystemBarBackgroundPainter;
- private final Rect mTaskBounds;
private final Rect mFrame = new Rect();
private final Rect mSystemBarInsets = new Rect();
+ private final int mSnapshotW;
+ private final int mSnapshotH;
private boolean mSizeMismatch;
public SnapshotSurface(SurfaceControl rootSurface, TaskSnapshot snapshot,
- CharSequence title,
- Rect taskBounds) {
+ CharSequence title) {
mRootSurface = rootSurface;
mSnapshot = snapshot;
mTitle = title;
- mTaskBounds = taskBounds;
+ final HardwareBuffer hwBuffer = snapshot.getHardwareBuffer();
+ mSnapshotW = hwBuffer.getWidth();
+ mSnapshotH = hwBuffer.getHeight();
}
/**
* Initiate system bar painter to draw the system bar background.
*/
- void initiateSystemBarPainter(int windowFlags, int windowPrivateFlags,
+ @VisibleForTesting
+ public void initiateSystemBarPainter(int windowFlags, int windowPrivateFlags,
int appearance, ActivityManager.TaskDescription taskDescription,
@WindowInsets.Type.InsetsType int requestedVisibleTypes) {
mSystemBarBackgroundPainter = new SystemBarBackgroundPainter(windowFlags,
@@ -143,14 +139,13 @@ public class SnapshotDrawerUtils {
}
/**
- * Set frame size.
+ * Set frame size that the snapshot should fill. It is the bounds of a task or activity.
*/
- void setFrames(Rect frame, Rect systemBarInsets) {
+ @VisibleForTesting
+ public void setFrames(Rect frame, Rect systemBarInsets) {
mFrame.set(frame);
mSystemBarInsets.set(systemBarInsets);
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- mSizeMismatch = (mFrame.width() != snapshot.getWidth()
- || mFrame.height() != snapshot.getHeight());
+ mSizeMismatch = (mFrame.width() != mSnapshotW || mFrame.height() != mSnapshotH);
mSystemBarBackgroundPainter.setInsets(systemBarInsets);
}
@@ -186,7 +181,7 @@ public class SnapshotDrawerUtils {
// We consider nearly matched dimensions as there can be rounding errors and the user
// won't notice very minute differences from scaling one dimension more than the other
- boolean aspectRatioMismatch = !isAspectRatioMatch(mFrame, mSnapshot);
+ boolean aspectRatioMismatch = !isAspectRatioMatch(mFrame, mSnapshotW, mSnapshotH);
// Keep a reference to it such that it doesn't get destroyed when finalized.
SurfaceControl childSurfaceControl = new SurfaceControl.Builder(session)
@@ -198,12 +193,14 @@ public class SnapshotDrawerUtils {
.build();
final Rect frame;
+ final Rect letterboxInsets = mSnapshot.getLetterboxInsets();
+ float offsetX = letterboxInsets.left;
+ float offsetY = letterboxInsets.top;
// We can just show the surface here as it will still be hidden as the parent is
// still hidden.
mTransaction.show(childSurfaceControl);
if (aspectRatioMismatch) {
Rect crop = null;
- final Rect letterboxInsets = mSnapshot.getLetterboxInsets();
if (letterboxInsets.left != 0 || letterboxInsets.top != 0
|| letterboxInsets.right != 0 || letterboxInsets.bottom != 0) {
// Clip off letterbox.
@@ -214,23 +211,27 @@ public class SnapshotDrawerUtils {
// if letterbox doesn't match window frame, try crop by content insets
if (aspectRatioMismatch) {
// Clip off ugly navigation bar.
- crop = calculateSnapshotCrop(mSnapshot.getContentInsets());
+ final Rect contentInsets = mSnapshot.getContentInsets();
+ crop = calculateSnapshotCrop(contentInsets);
+ offsetX = contentInsets.left;
+ offsetY = contentInsets.top;
}
frame = calculateSnapshotFrame(crop);
- mTransaction.setWindowCrop(childSurfaceControl, crop);
- mTransaction.setPosition(childSurfaceControl, frame.left, frame.top);
- sTmpSnapshotSize.set(crop);
- sTmpDstFrame.set(frame);
+ mTransaction.setCrop(childSurfaceControl, crop);
} else {
frame = null;
- sTmpSnapshotSize.set(0, 0, buffer.getWidth(), buffer.getHeight());
- sTmpDstFrame.set(mFrame);
- sTmpDstFrame.offsetTo(0, 0);
}
- // Scale the mismatch dimensions to fill the task bounds
- sSnapshotMatrix.setRectToRect(sTmpSnapshotSize, sTmpDstFrame, Matrix.ScaleToFit.FILL);
- mTransaction.setMatrix(childSurfaceControl, sSnapshotMatrix, sTmpFloat9);
+ // Align the snapshot with content area.
+ if (offsetX != 0f || offsetY != 0f) {
+ mTransaction.setPosition(childSurfaceControl,
+ -offsetX * mFrame.width() / mSnapshot.getTaskSize().x,
+ -offsetY * mFrame.height() / mSnapshot.getTaskSize().y);
+ }
+ // Scale the mismatch dimensions to fill the target frame.
+ final float scaleX = (float) mFrame.width() / mSnapshotW;
+ final float scaleY = (float) mFrame.height() / mSnapshotH;
+ mTransaction.setScale(childSurfaceControl, scaleX, scaleY);
mTransaction.setColorSpace(childSurfaceControl, mSnapshot.getColorSpace());
mTransaction.setBuffer(childSurfaceControl, mSnapshot.getHardwareBuffer());
@@ -261,17 +262,17 @@ public class SnapshotDrawerUtils {
* @param insets Content insets or Letterbox insets
* @return crop rect in snapshot coordinate space.
*/
- Rect calculateSnapshotCrop(@NonNull Rect insets) {
+ @VisibleForTesting
+ public Rect calculateSnapshotCrop(@NonNull Rect insets) {
final Rect rect = new Rect();
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- rect.set(0, 0, snapshot.getWidth(), snapshot.getHeight());
+ rect.set(0, 0, mSnapshotW, mSnapshotH);
- final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
- final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
+ final float scaleX = (float) mSnapshotW / mSnapshot.getTaskSize().x;
+ final float scaleY = (float) mSnapshotH / mSnapshot.getTaskSize().y;
// Let's remove all system decorations except the status bar, but only if the task is at
// the very top of the screen.
- final boolean isTop = mTaskBounds.top == 0 && mFrame.top == 0;
+ final boolean isTop = mFrame.top == 0;
rect.inset((int) (insets.left * scaleX),
isTop ? 0 : (int) (insets.top * scaleY),
(int) (insets.right * scaleX),
@@ -284,10 +285,10 @@ public class SnapshotDrawerUtils {
*
* @param crop rect that is in snapshot coordinate space.
*/
- Rect calculateSnapshotFrame(Rect crop) {
- final HardwareBuffer snapshot = mSnapshot.getHardwareBuffer();
- final float scaleX = (float) snapshot.getWidth() / mSnapshot.getTaskSize().x;
- final float scaleY = (float) snapshot.getHeight() / mSnapshot.getTaskSize().y;
+ @VisibleForTesting
+ public Rect calculateSnapshotFrame(Rect crop) {
+ final float scaleX = (float) mSnapshotW / mSnapshot.getTaskSize().x;
+ final float scaleY = (float) mSnapshotH / mSnapshot.getTaskSize().y;
// Rescale the frame from snapshot to window coordinate space
final Rect frame = new Rect(0, 0,
@@ -303,7 +304,8 @@ public class SnapshotDrawerUtils {
/**
* Draw status bar and navigation bar background.
*/
- void drawBackgroundAndBars(Canvas c, Rect frame) {
+ @VisibleForTesting
+ public void drawBackgroundAndBars(Canvas c, Rect frame) {
final int statusBarHeight = mSystemBarBackgroundPainter.getStatusBarColorViewHeight();
final boolean fillHorizontally = c.getWidth() > frame.right;
final boolean fillVertically = c.getHeight() > frame.bottom;
@@ -320,33 +322,27 @@ public class SnapshotDrawerUtils {
/**
* Ask system bar background painter to draw status bar background.
- *
*/
- void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame) {
+ @VisibleForTesting
+ public void drawStatusBarBackground(Canvas c, @Nullable Rect alreadyDrawnFrame) {
mSystemBarBackgroundPainter.drawStatusBarBackground(c, alreadyDrawnFrame,
mSystemBarBackgroundPainter.getStatusBarColorViewHeight());
}
/**
* Ask system bar background painter to draw navigation bar background.
- *
*/
- void drawNavigationBarBackground(Canvas c) {
+ @VisibleForTesting
+ public void drawNavigationBarBackground(Canvas c) {
mSystemBarBackgroundPainter.drawNavigationBarBackground(c);
}
}
- /**
- * @return true if the aspect ratio match between a frame and a snapshot buffer.
- */
- public static boolean isAspectRatioMatch(Rect frame, TaskSnapshot snapshot) {
+ private static boolean isAspectRatioMatch(Rect frame, int w, int h) {
if (frame.isEmpty()) {
return false;
}
- final HardwareBuffer buffer = snapshot.getHardwareBuffer();
- return Math.abs(
- ((float) buffer.getWidth() / buffer.getHeight())
- - ((float) frame.width() / frame.height())) <= 0.01f;
+ return Math.abs(((float) w / h) - ((float) frame.width() / frame.height())) <= 0.01f;
}
private static boolean isAspectRatioMatch(Rect frame1, Rect frame2) {
@@ -378,14 +374,14 @@ public class SnapshotDrawerUtils {
*/
public static void drawSnapshotOnSurface(StartingWindowInfo info, WindowManager.LayoutParams lp,
SurfaceControl rootSurface, TaskSnapshot snapshot,
- Rect configBounds, Rect windowBounds, InsetsState topWindowInsetsState,
+ Rect windowBounds, InsetsState topWindowInsetsState,
boolean releaseAfterDraw) {
if (windowBounds.isEmpty()) {
Log.e(TAG, "Unable to draw snapshot on an empty windowBounds");
return;
}
final SnapshotSurface drawSurface = new SnapshotSurface(
- rootSurface, snapshot, lp.getTitle(), configBounds);
+ rootSurface, snapshot, lp.getTitle());
final WindowManager.LayoutParams attrs = info.topOpaqueWindowLayoutParams;
final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
diff --git a/core/java/android/window/StartingWindowInfo.java b/core/java/android/window/StartingWindowInfo.java
index 260d9a82472f..72df343a2dbe 100644
--- a/core/java/android/window/StartingWindowInfo.java
+++ b/core/java/android/window/StartingWindowInfo.java
@@ -22,6 +22,7 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.TaskInfo;
import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
@@ -79,11 +80,17 @@ public final class StartingWindowInfo implements Parcelable {
/**
* The {@link TaskInfo} from this task.
- * @hide
+ * <p>Note that the configuration of this taskInfo could be from the top activity of its task.
+ * Because only activity contains persisted configuration (e.g. night mode, language). Besides,
+ * it can also be used for activity level snapshot.
*/
@NonNull
public ActivityManager.RunningTaskInfo taskInfo;
+ /** The bounds of the target task. */
+ @NonNull
+ public final Rect taskBounds = new Rect();
+
/**
* The {@link ActivityInfo} of the target activity which to create the starting window.
* It can be null if the info is the same as the top in task info.
@@ -253,6 +260,7 @@ public final class StartingWindowInfo implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeTypedObject(taskInfo, flags);
+ taskBounds.writeToParcel(dest, flags);
dest.writeTypedObject(targetActivityInfo, flags);
dest.writeInt(startingWindowTypeParameter);
dest.writeTypedObject(topOpaqueWindowInsetsState, flags);
@@ -269,6 +277,7 @@ public final class StartingWindowInfo implements Parcelable {
void readFromParcel(@NonNull Parcel source) {
taskInfo = source.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR);
+ taskBounds.readFromParcel(source);
targetActivityInfo = source.readTypedObject(ActivityInfo.CREATOR);
startingWindowTypeParameter = source.readInt();
topOpaqueWindowInsetsState = source.readTypedObject(InsetsState.CREATOR);
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 91ef324a7df0..0d1be3814cb5 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3656,6 +3656,7 @@
"emergency" = Launch emergency dialer
"lockdown" = Lock down device until the user authenticates
"logout" = Logout the current user
+ "system_update" = Launch System Update screen
-->
<string-array translatable="false" name="config_globalActionsList">
<item>emergency</item>
diff --git a/core/res/res/values/public-final.xml b/core/res/res/values/public-final.xml
index daa0f553f47a..d421944917ea 100644
--- a/core/res/res/values/public-final.xml
+++ b/core/res/res/values/public-final.xml
@@ -3741,4 +3741,185 @@
<!-- @hide @SystemApi -->
<public type="bool" name="config_enableDefaultNotesForWorkProfile" id="0x0111000b" />
+ <!-- ===============================================================
+ Resources added in version NEXT of the platform
+
+ NOTE: After this version of the platform is forked, changes cannot be made to the root
+ branch's groups for that release. Only merge changes to the forked platform branch.
+ =============================================================== -->
+ <eat-comment/>
+
+ <staging-public-group-final type="attr" first-id="0x01bd0000">
+ <!-- @FlaggedApi("android.content.res.default_locale") -->
+ <public name="defaultLocale"/>
+ <!-- @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime")
+ @hide @SystemApi -->
+ <public name="isVirtualDeviceOnly"/>
+ <!-- Marking this entry as removed since it's not being finalized -->
+ <public name="removed_optional" />
+ <!-- Marking this entry as removed since it's not being finalized -->
+ <public name="removed_adServiceTypes" />
+ <!-- @hide @SystemApi @FlaggedApi("android.content.res.manifest_flagging") -->
+ <public name="featureFlag"/>
+ <!-- @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") -->
+ <public name="systemUserOnly"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="allow"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="query"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="queryPrefix"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="queryPattern"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="queryAdvancedPattern"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="querySuffix"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="fragmentPrefix"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="fragmentPattern"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="fragmentAdvancedPattern"/>
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public name="fragmentSuffix"/>
+ <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
+ <public name="useBoundsForWidth"/>
+ <!-- @FlaggedApi("android.nfc.nfc_read_polling_loop") -->
+ <public name="autoTransact"/>
+ <!-- @FlaggedApi("com.android.window.flags.enforce_edge_to_edge") -->
+ <public name="windowOptOutEdgeToEdgeEnforcement"/>
+ <!-- @FlaggedApi("android.security.content_uri_permission_apis") -->
+ <public name="requireContentUriPermissionFromCaller" />
+ <!-- Marking this entry as removed since it's not being finalized -->
+ <public name="removed_languageSettingsActivity" />
+ <!-- @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") -->
+ <public name="useLocalePreferredLineHeightForMinimum"/>
+ <!-- @FlaggedApi("android.view.flags.sensitive_content_app_protection_api") -->
+ <public name="contentSensitivity" />
+ <!-- @FlaggedApi("android.view.inputmethod.connectionless_handwriting") -->
+ <public name="supportsConnectionlessStylusHandwriting" />
+ <!-- @FlaggedApi("android.nfc.nfc_observe_mode") -->
+ <public name="shouldDefaultToObserveMode"/>
+ <!-- @FlaggedApi("android.security.asm_restrictions_enabled") -->
+ <public name="allowCrossUidActivitySwitchFromBelow"/>
+ <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
+ <public name="shiftDrawingOffsetForStartOverhang" />
+ <!-- @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") -->
+ <public name="windowIsFrameRatePowerSavingsBalanced"/>
+ <!-- Marking this entry as removed since it's not being finalized -->
+ <public name="removed_dreamCategory" />
+ </staging-public-group-final>
+
+ <!-- @FlaggedApi("android.content.res.default_locale") -->
+ <public type="attr" name="defaultLocale" id="0x01010688" />
+ <!-- @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime")
+ @hide @SystemApi -->
+ <public type="attr" name="isVirtualDeviceOnly" id="0x01010689" />
+ <!-- @hide @SystemApi @FlaggedApi("android.content.res.manifest_flagging") -->
+ <public type="attr" name="featureFlag" id="0x0101068c" />
+ <!-- @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") -->
+ <public type="attr" name="systemUserOnly" id="0x0101068d" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="allow" id="0x0101068e" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="query" id="0x0101068f" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="queryPrefix" id="0x01010690" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="queryPattern" id="0x01010691" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="queryAdvancedPattern" id="0x01010692" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="querySuffix" id="0x01010693" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="fragmentPrefix" id="0x01010694" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="fragmentPattern" id="0x01010695" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="fragmentAdvancedPattern" id="0x01010696" />
+ <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
+ <public type="attr" name="fragmentSuffix" id="0x01010697" />
+ <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
+ <public type="attr" name="useBoundsForWidth" id="0x01010698" />
+ <!-- @FlaggedApi("android.nfc.nfc_read_polling_loop") -->
+ <public type="attr" name="autoTransact" id="0x01010699" />
+ <!-- @FlaggedApi("com.android.window.flags.enforce_edge_to_edge") -->
+ <public type="attr" name="windowOptOutEdgeToEdgeEnforcement" id="0x0101069a" />
+ <!-- @FlaggedApi("android.security.content_uri_permission_apis") -->
+ <public type="attr" name="requireContentUriPermissionFromCaller" id="0x0101069b" />
+ <!-- @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") -->
+ <public type="attr" name="useLocalePreferredLineHeightForMinimum" id="0x0101069d" />
+ <!-- @FlaggedApi("android.view.flags.sensitive_content_app_protection_api") -->
+ <public type="attr" name="contentSensitivity" id="0x0101069e" />
+ <!-- @FlaggedApi("android.view.inputmethod.connectionless_handwriting") -->
+ <public type="attr" name="supportsConnectionlessStylusHandwriting" id="0x0101069f" />
+ <!-- @FlaggedApi("android.nfc.nfc_observe_mode") -->
+ <public type="attr" name="shouldDefaultToObserveMode" id="0x010106a0" />
+ <!-- @FlaggedApi("android.security.asm_restrictions_enabled") -->
+ <public type="attr" name="allowCrossUidActivitySwitchFromBelow" id="0x010106a1" />
+ <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
+ <public type="attr" name="shiftDrawingOffsetForStartOverhang" id="0x010106a2" />
+ <!-- @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") -->
+ <public type="attr" name="windowIsFrameRatePowerSavingsBalanced" id="0x010106a3" />
+
+ <staging-public-group-final type="string" first-id="0x01ba0000">
+ <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.retail_demo_role_enabled") -->
+ <public name="config_defaultRetailDemo" />
+ <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.wallet_role_enabled") -->
+ <public name="config_defaultWallet" />
+ </staging-public-group-final>
+
+ <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.retail_demo_role_enabled") -->
+ <public type="string" name="config_defaultRetailDemo" id="0x01040048" />
+ <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.wallet_role_enabled") -->
+ <public type="string" name="config_defaultWallet" id="0x01040049" />
+
+ <staging-public-group-final type="dimen" first-id="0x01b90000">
+ <!-- System corner radius baseline sizes. Used by Material styling of rounded corner shapes-->
+ <public name="removed_system_corner_radius_xsmall" />
+ <public name="removed_system_corner_radius_small" />
+ <public name="removed_system_corner_radius_medium" />
+ <public name="removed_system_corner_radius_large" />
+ <public name="removed_system_corner_radius_xlarge" />
+ </staging-public-group-final>
+
+ <!-- System corner radius baseline sizes. Used by Material styling of rounded corner shapes-->
+
+ <staging-public-group-final type="color" first-id="0x01b80000">
+ <public name="system_surface_disabled"/>
+ <public name="system_on_surface_disabled"/>
+ <public name="system_outline_disabled"/>
+ <public name="system_error_0"/>
+ <public name="system_error_10"/>
+ <public name="system_error_50"/>
+ <public name="system_error_100"/>
+ <public name="system_error_200"/>
+ <public name="system_error_300"/>
+ <public name="system_error_400"/>
+ <public name="system_error_500"/>
+ <public name="system_error_600"/>
+ <public name="system_error_700"/>
+ <public name="system_error_800"/>
+ <public name="system_error_900"/>
+ <public name="system_error_1000"/>
+ </staging-public-group-final>
+
+ <public type="color" name="system_surface_disabled" id="0x010600c2" />
+ <public type="color" name="system_on_surface_disabled" id="0x010600c3" />
+ <public type="color" name="system_outline_disabled" id="0x010600c4" />
+ <public type="color" name="system_error_0" id="0x010600c5" />
+ <public type="color" name="system_error_10" id="0x010600c6" />
+ <public type="color" name="system_error_50" id="0x010600c7" />
+ <public type="color" name="system_error_100" id="0x010600c8" />
+ <public type="color" name="system_error_200" id="0x010600c9" />
+ <public type="color" name="system_error_300" id="0x010600ca" />
+ <public type="color" name="system_error_400" id="0x010600cb" />
+ <public type="color" name="system_error_500" id="0x010600cc" />
+ <public type="color" name="system_error_600" id="0x010600cd" />
+ <public type="color" name="system_error_700" id="0x010600ce" />
+ <public type="color" name="system_error_800" id="0x010600cf" />
+ <public type="color" name="system_error_900" id="0x010600d0" />
+ <public type="color" name="system_error_1000" id="0x010600d1" />
+
</resources>
diff --git a/core/res/res/values/public-staging.xml b/core/res/res/values/public-staging.xml
index c84f781d695e..b64334f7f95a 100644
--- a/core/res/res/values/public-staging.xml
+++ b/core/res/res/values/public-staging.xml
@@ -109,143 +109,66 @@
=============================================================== -->
<eat-comment/>
- <staging-public-group type="attr" first-id="0x01bd0000">
- <!-- @FlaggedApi("android.content.res.default_locale") -->
- <public name="defaultLocale"/>
- <!-- @FlaggedApi("android.companion.virtual.flags.vdm_custom_ime")
- @hide @SystemApi -->
- <public name="isVirtualDeviceOnly"/>
- <!-- @FlaggedApi("android.content.pm.sdk_lib_independence") -->
+ <staging-public-group type="attr" first-id="0x01b70000">
+ <!-- @FlaggedApi("android.content.pm.sdk_lib_independence") -->
<public name="optional"/>
<!-- @FlaggedApi("android.media.tv.flags.enable_ad_service_fw") -->
<public name="adServiceTypes" />
- <!-- @hide @SystemApi @FlaggedApi("android.content.res.manifest_flagging") -->
- <public name="featureFlag"/>
- <!-- @FlaggedApi("android.multiuser.enable_system_user_only_for_services_and_providers") -->
- <public name="systemUserOnly"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="allow"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="query"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="queryPrefix"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="queryPattern"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="queryAdvancedPattern"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="querySuffix"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="fragmentPrefix"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="fragmentPattern"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="fragmentAdvancedPattern"/>
- <!-- @FlaggedApi("android.content.pm.relative_reference_intent_filters") -->
- <public name="fragmentSuffix"/>
- <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
- <public name="useBoundsForWidth"/>
- <!-- @FlaggedApi("android.nfc.nfc_read_polling_loop") -->
- <public name="autoTransact"/>
- <!-- @FlaggedApi("com.android.window.flags.enforce_edge_to_edge") -->
- <public name="windowOptOutEdgeToEdgeEnforcement"/>
- <!-- @FlaggedApi("android.security.content_uri_permission_apis") -->
- <public name="requireContentUriPermissionFromCaller" />
<!-- @FlaggedApi("android.view.inputmethod.ime_switcher_revamp") -->
<public name="languageSettingsActivity"/>
- <!-- @FlaggedApi("com.android.text.flags.fix_line_height_for_locale") -->
- <public name="useLocalePreferredLineHeightForMinimum"/>
- <!-- @FlaggedApi("android.view.flags.sensitive_content_app_protection_api") -->
- <public name="contentSensitivity" />
- <!-- @FlaggedApi("android.view.inputmethod.connectionless_handwriting") -->
- <public name="supportsConnectionlessStylusHandwriting" />
- <!-- @FlaggedApi("android.nfc.nfc_observe_mode") -->
- <public name="shouldDefaultToObserveMode"/>
- <!-- @FlaggedApi("android.security.asm_restrictions_enabled") -->
- <public name="allowCrossUidActivitySwitchFromBelow"/>
- <!-- @FlaggedApi("com.android.text.flags.use_bounds_for_width") -->
- <public name="shiftDrawingOffsetForStartOverhang" />
- <!-- @FlaggedApi("android.view.flags.toolkit_set_frame_rate_read_only") -->
- <public name="windowIsFrameRatePowerSavingsBalanced"/>
<!-- @FlaggedApi("android.service.controls.flags.Flags.FLAG_HOME_PANEL_DREAM") -->
<public name="dreamCategory"/>
</staging-public-group>
- <staging-public-group type="id" first-id="0x01bc0000">
+ <staging-public-group type="id" first-id="0x01b60000">
</staging-public-group>
- <staging-public-group type="style" first-id="0x01bb0000">
+ <staging-public-group type="style" first-id="0x01b50000">
</staging-public-group>
- <staging-public-group type="string" first-id="0x01ba0000">
- <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.retail_demo_role_enabled") -->
- <public name="config_defaultRetailDemo" />
- <!-- @hide @SystemApi @FlaggedApi("android.permission.flags.wallet_role_enabled") -->
- <public name="config_defaultWallet" />
+ <staging-public-group type="string" first-id="0x01b40000">
</staging-public-group>
- <staging-public-group type="dimen" first-id="0x01b90000">
- <!-- System corner radius baseline sizes. Used by Material styling of rounded corner shapes-->
- <public name="removed_system_corner_radius_xsmall" />
- <public name="removed_system_corner_radius_small" />
- <public name="removed_system_corner_radius_medium" />
- <public name="removed_system_corner_radius_large" />
- <public name="removed_system_corner_radius_xlarge" />
+ <staging-public-group type="dimen" first-id="0x01b30000">
</staging-public-group>
- <staging-public-group type="color" first-id="0x01b80000">
- <public name="system_surface_disabled"/>
- <public name="system_on_surface_disabled"/>
- <public name="system_outline_disabled"/>
- <public name="system_error_0"/>
- <public name="system_error_10"/>
- <public name="system_error_50"/>
- <public name="system_error_100"/>
- <public name="system_error_200"/>
- <public name="system_error_300"/>
- <public name="system_error_400"/>
- <public name="system_error_500"/>
- <public name="system_error_600"/>
- <public name="system_error_700"/>
- <public name="system_error_800"/>
- <public name="system_error_900"/>
- <public name="system_error_1000"/>
+ <staging-public-group type="color" first-id="0x01b20000">
</staging-public-group>
- <staging-public-group type="array" first-id="0x01b70000">
+ <staging-public-group type="array" first-id="0x01b10000">
</staging-public-group>
- <staging-public-group type="drawable" first-id="0x01b60000">
+ <staging-public-group type="drawable" first-id="0x01b00000">
</staging-public-group>
- <staging-public-group type="layout" first-id="0x01b50000">
+ <staging-public-group type="layout" first-id="0x01af0000">
</staging-public-group>
- <staging-public-group type="anim" first-id="0x01b40000">
+ <staging-public-group type="anim" first-id="0x01ae0000">
</staging-public-group>
- <staging-public-group type="animator" first-id="0x01b30000">
+ <staging-public-group type="animator" first-id="0x01ad0000">
</staging-public-group>
- <staging-public-group type="interpolator" first-id="0x01b20000">
+ <staging-public-group type="interpolator" first-id="0x01ac0000">
</staging-public-group>
- <staging-public-group type="mipmap" first-id="0x01b10000">
+ <staging-public-group type="mipmap" first-id="0x01ab0000">
</staging-public-group>
- <staging-public-group type="integer" first-id="0x01b00000">
+ <staging-public-group type="integer" first-id="0x01aa0000">
</staging-public-group>
- <staging-public-group type="transition" first-id="0x01af0000">
+ <staging-public-group type="transition" first-id="0x01a90000">
</staging-public-group>
- <staging-public-group type="raw" first-id="0x01ae0000">
+ <staging-public-group type="raw" first-id="0x01a80000">
</staging-public-group>
- <staging-public-group type="bool" first-id="0x01ad0000">
+ <staging-public-group type="bool" first-id="0x01a70000">
</staging-public-group>
- <staging-public-group type="fraction" first-id="0x01ac0000">
+ <staging-public-group type="fraction" first-id="0x01a60000">
</staging-public-group>
</resources>
diff --git a/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java b/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
index 036154634ae7..6c8dcd39e223 100644
--- a/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
+++ b/core/tests/coretests/src/android/window/SnapshotDrawerUtilsTest.java
@@ -77,7 +77,7 @@ public class SnapshotDrawerUtilsTest {
Color.RED, Color.BLUE);
mSnapshotSurface = new SnapshotDrawerUtils.SnapshotSurface(
- new SurfaceControl(), snapshot, "Test", taskBounds);
+ new SurfaceControl(), snapshot, "Test");
mSnapshotSurface.initiateSystemBarPainter(windowFlags, 0, 0,
taskDescription, WindowInsets.Type.defaultVisible());
}
@@ -167,14 +167,16 @@ public class SnapshotDrawerUtilsTest {
@Test
public void testCalculateSnapshotCrop_taskNotOnTop() {
final Rect contentInsets = new Rect(0, 10, 0, 10);
- setupSurface(100, 100, contentInsets, 0, new Rect(0, 50, 100, 150));
+ final Rect bounds = new Rect(0, 50, 100, 150);
+ setupSurface(100, 100, contentInsets, 0, bounds);
+ mSnapshotSurface.setFrames(bounds, contentInsets);
assertEquals(new Rect(0, 10, 100, 90),
mSnapshotSurface.calculateSnapshotCrop(contentInsets));
}
@Test
public void testCalculateSnapshotCrop_navBarLeft() {
- final Rect contentInsets = new Rect(0, 10, 0, 0);
+ final Rect contentInsets = new Rect(10, 0, 0, 0);
setupSurface(100, 100, contentInsets, 0, new Rect(0, 0, 100, 100));
assertEquals(new Rect(10, 0, 100, 100),
mSnapshotSurface.calculateSnapshotCrop(contentInsets));
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 6834e6d3123f..17121c8de428 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -702,10 +702,12 @@ public abstract class WMShellBaseModule {
ShellInit shellInit,
ShellController shellController,
Transitions transitions,
+ TaskStackListenerImpl taskStackListener,
@ShellMainThread Handler mainHandler,
@ShellMainThread ShellExecutor mainExecutor) {
return new KeyguardTransitionHandler(
- shellInit, shellController, transitions, mainHandler, mainExecutor);
+ shellInit, shellController, transitions, taskStackListener, mainHandler,
+ mainExecutor);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
index 863a51ad575b..9eaf7e4e2e21 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/keyguard/KeyguardTransitionHandler.java
@@ -20,6 +20,7 @@ import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_DREAM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.service.dreams.Flags.dismissDreamOnKeyguardDismiss;
import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
@@ -44,10 +45,13 @@ import android.window.IRemoteTransition;
import android.window.IRemoteTransitionFinishedCallback;
import android.window.TransitionInfo;
import android.window.TransitionRequestInfo;
+import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.TaskStackListenerCallback;
+import com.android.wm.shell.common.TaskStackListenerImpl;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.shared.annotations.ExternalThread;
import com.android.wm.shell.sysui.KeyguardChangeListener;
@@ -62,7 +66,8 @@ import com.android.wm.shell.transition.Transitions.TransitionFinishCallback;
* <p>This takes the highest priority.
*/
public class KeyguardTransitionHandler
- implements Transitions.TransitionHandler, KeyguardChangeListener {
+ implements Transitions.TransitionHandler, KeyguardChangeListener,
+ TaskStackListenerCallback {
private static final String TAG = "KeyguardTransition";
private final Transitions mTransitions;
@@ -71,6 +76,7 @@ public class KeyguardTransitionHandler
private final ShellExecutor mMainExecutor;
private final ArrayMap<IBinder, StartedTransition> mStartedTransitions = new ArrayMap<>();
+ private final TaskStackListenerImpl mTaskStackListener;
/**
* Local IRemoteTransition implementations registered by the keyguard service.
@@ -87,6 +93,8 @@ public class KeyguardTransitionHandler
// Last value reported by {@link KeyguardChangeListener}.
private boolean mKeyguardShowing = true;
+ @Nullable
+ private WindowContainerToken mDreamToken;
private final class StartedTransition {
final TransitionInfo mInfo;
@@ -105,18 +113,23 @@ public class KeyguardTransitionHandler
@NonNull ShellInit shellInit,
@NonNull ShellController shellController,
@NonNull Transitions transitions,
+ @NonNull TaskStackListenerImpl taskStackListener,
@NonNull Handler mainHandler,
@NonNull ShellExecutor mainExecutor) {
mTransitions = transitions;
mShellController = shellController;
mMainHandler = mainHandler;
mMainExecutor = mainExecutor;
+ mTaskStackListener = taskStackListener;
shellInit.addInitCallback(this::onInit, this);
}
private void onInit() {
mTransitions.addHandler(this);
mShellController.addKeyguardChangeListener(this);
+ if (dismissDreamOnKeyguardDismiss()) {
+ mTaskStackListener.addListener(this);
+ }
}
/**
@@ -142,6 +155,11 @@ public class KeyguardTransitionHandler
}
@Override
+ public void onTaskMovedToFront(ActivityManager.RunningTaskInfo taskInfo) {
+ mDreamToken = taskInfo.getActivityType() == ACTIVITY_TYPE_DREAM ? taskInfo.token : null;
+ }
+
+ @Override
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@@ -271,6 +289,13 @@ public class KeyguardTransitionHandler
@Override
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
@NonNull TransitionRequestInfo request) {
+ if (dismissDreamOnKeyguardDismiss()
+ && (request.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0
+ && mDreamToken != null) {
+ // Dismiss the dream in the same transaction, so that it isn't visible once the device
+ // is unlocked.
+ return new WindowContainerTransaction().removeTask(mDreamToken);
+ }
return null;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index e727945d6ee6..66b3553bea09 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -29,7 +29,6 @@ import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskDescription;
import android.graphics.Paint;
-import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.IBinder;
@@ -103,8 +102,6 @@ public class TaskSnapshotWindow {
return null;
}
- final Point taskSize = snapshot.getTaskSize();
- final Rect taskBounds = new Rect(0, 0, taskSize.x, taskSize.y);
final int orientation = snapshot.getOrientation();
final int displayId = runningTaskInfo.displayId;
@@ -160,7 +157,7 @@ public class TaskSnapshotWindow {
}
SnapshotDrawerUtils.drawSnapshotOnSurface(info, layoutParams, surfaceControl, snapshot,
- taskBounds, tmpFrames.frame, topWindowInsetsState, true /* releaseAfterDraw */);
+ info.taskBounds, topWindowInsetsState, true /* releaseAfterDraw */);
snapshotSurface.mHasDrawn = true;
snapshotSurface.reportDrawn();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
index fed2f34b5e0c..5c814dcc9b16 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/WindowlessSnapshotWindowCreator.java
@@ -23,7 +23,6 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.app.ActivityManager;
import android.content.Context;
-import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.view.Display;
@@ -77,15 +76,13 @@ class WindowlessSnapshotWindowCreator {
runningTaskInfo.configuration, rootSurface);
final SurfaceControlViewHost mViewHost = new SurfaceControlViewHost(
mContext, display, wlw, "WindowlessSnapshotWindowCreator");
- final Point taskSize = snapshot.getTaskSize();
- final Rect snapshotBounds = new Rect(0, 0, taskSize.x, taskSize.y);
final Rect windowBounds = runningTaskInfo.configuration.windowConfiguration.getBounds();
final InsetsState topWindowInsetsState = info.topOpaqueWindowInsetsState;
final FrameLayout rootLayout = new FrameLayout(
mSplashscreenContentDrawer.createViewContextWrapper(mContext));
mViewHost.setView(rootLayout, lp);
SnapshotDrawerUtils.drawSnapshotOnSurface(info, lp, wlw.mChildSurface, snapshot,
- snapshotBounds, windowBounds, topWindowInsetsState, false /* releaseAfterDraw */);
+ windowBounds, topWindowInsetsState, false /* releaseAfterDraw */);
final ActivityManager.TaskDescription taskDescription =
SnapshotDrawerUtils.getOrCreateTaskDescription(runningTaskInfo);
diff --git a/location/java/android/location/flags/location.aconfig b/location/java/android/location/flags/location.aconfig
index 49810294a888..5f84862ddf49 100644
--- a/location/java/android/location/flags/location.aconfig
+++ b/location/java/android/location/flags/location.aconfig
@@ -80,10 +80,13 @@ flag {
}
flag {
- name: "subscriptions_listener_thread"
+ name: "subscriptions_changed_listener_thread"
namespace: "location"
- description: "Flag for running onSubscriptionsChangeListener on FgThread"
+ description: "Flag for running onSubscriptionsChangedListener on FgThread"
bug: "332451908"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
flag {
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 151581134009..adbfc72cd684 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1745,4 +1745,7 @@
<string name="feminine">Feminine</string>
<!-- List entry in developer settings to set the grammatical gender to Masculine [CHAR LIMIT=30]-->
<string name="masculine">Masculine</string>
+
+ <!-- The name of the screen for seeing and installing system updates. [CHAR LIMIT=40]-->
+ <string name="system_update_settings_list_item_title">System Updates</string>
</resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 9e9350b1a17a..2e9075caf344 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -186,9 +186,14 @@ public class SettingsHelper {
sendBroadcast = sBroadcastOnRestore.contains(name);
sendBroadcastSystemUI = sBroadcastOnRestoreSystemUI.contains(name);
- if (sendBroadcast || sendBroadcastSystemUI) {
+ if (sendBroadcast) {
// TODO: http://b/22388012
oldValue = table.lookup(cr, name, UserHandle.USER_SYSTEM);
+ } else if (sendBroadcastSystemUI) {
+ // This is only done for broadcasts sent to system ui as the consumers are known.
+ // It would probably be correct to do it for the ones sent to the system, but consumers
+ // may be depending on the current behavior.
+ oldValue = table.lookup(cr, name, context.getUserId());
}
try {
@@ -266,7 +271,7 @@ public class SettingsHelper {
if (sendBroadcastSystemUI) {
intent.setPackage(
context.getString(com.android.internal.R.string.config_systemUi));
- context.sendBroadcastAsUser(intent, UserHandle.SYSTEM, null);
+ context.sendBroadcastAsUser(intent, context.getUser(), null);
}
}
}
diff --git a/packages/Shell/Android.bp b/packages/Shell/Android.bp
index c87916fa3b95..253145468e47 100644
--- a/packages/Shell/Android.bp
+++ b/packages/Shell/Android.bp
@@ -19,6 +19,9 @@ android_app {
include_dirs: ["frameworks/native/cmds/dumpstate/binder"],
},
static_libs: shell_static_libs,
+ libs: [
+ "device_policy_aconfig_flags_lib",
+ ],
platform_apis: true,
certificate: "platform",
privileged: true,
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 5ac0e449b8e1..bcfd8f620f9c 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -16,6 +16,7 @@
package com.android.shell;
+import static android.app.admin.flags.Flags.onboardingBugreportStorageBugFix;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_TELEVISION;
import static android.os.Process.THREAD_PRIORITY_BACKGROUND;
@@ -89,10 +90,10 @@ import com.android.internal.app.ChooserActivity;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.google.android.collect.Lists;
-
import libcore.io.Streams;
+import com.google.android.collect.Lists;
+
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
@@ -109,6 +110,8 @@ import java.security.NoSuchAlgorithmException;
import java.text.NumberFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
@@ -442,10 +445,14 @@ public class BugreportProgressService extends Service {
}
}
- private static void sendRemoteBugreportFinishedBroadcast(Context context,
+ private void sendRemoteBugreportFinishedBroadcast(Context context,
String bugreportFileName, File bugreportFile, long nonce) {
- cleanupOldFiles(REMOTE_BUGREPORT_FILES_AMOUNT, REMOTE_MIN_KEEP_AGE,
- bugreportFile.getParentFile());
+ // Remote bugreports are stored in the same directory as normal bugreports, meaning that
+ // the remote bugreport storage limit will get applied to normal bugreports whenever a
+ // remote bugreport is triggered. The fix in cleanupOldFiles applies the normal bugreport
+ // limit to the remote bugreports as a quick fix.
+ cleanupOldFiles(
+ REMOTE_BUGREPORT_FILES_AMOUNT, REMOTE_MIN_KEEP_AGE, bugreportFile.getParentFile());
final Intent intent = new Intent(DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH);
final Uri bugreportUri = getUri(context, bugreportFile);
final String bugreportHash = generateFileHash(bugreportFileName);
@@ -496,12 +503,16 @@ public class BugreportProgressService extends Service {
return fileHash;
}
- static void cleanupOldFiles(final int minCount, final long minAge, File bugreportsDir) {
+ void cleanupOldFiles(final int minCount, final long minAge, File bugreportsDir) {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
- FileUtils.deleteOlderFiles(bugreportsDir, minCount, minAge);
+ if (onboardingBugreportStorageBugFix()) {
+ cleanupOldBugreports();
+ } else {
+ FileUtils.deleteOlderFiles(bugreportsDir, minCount, minAge);
+ }
} catch (RuntimeException e) {
Log.e(TAG, "RuntimeException deleting old files", e);
}
@@ -510,6 +521,42 @@ public class BugreportProgressService extends Service {
}.execute();
}
+ private void cleanupOldBugreports() {
+ final File[] files = mBugreportsDir.listFiles();
+ if (files == null) return;
+
+ // Sort with newest files first
+ Arrays.sort(files, new Comparator<File>() {
+ @Override
+ public int compare(File lhs, File rhs) {
+ return Long.compare(rhs.lastModified(), lhs.lastModified());
+ }
+ });
+
+ int normalBugreportFilesCount = 0;
+ int deferredBugreportFilesCount = 0;
+ for (int i = 0; i < files.length; i++) {
+ final File file = files[i];
+
+ // tmp files are deferred bugreports which have their separate storage limit
+ boolean isDeferredBugreportFile = file.getName().endsWith(".tmp");
+ if (isDeferredBugreportFile) {
+ deferredBugreportFilesCount++;
+ } else {
+ normalBugreportFilesCount++;
+ }
+ // Keep files newer than minAgeMs
+ final long age = System.currentTimeMillis() - file.lastModified();
+ final int count = isDeferredBugreportFile
+ ? deferredBugreportFilesCount : normalBugreportFilesCount;
+ if (count > MIN_KEEP_COUNT && age > MIN_KEEP_AGE) {
+ if (file.delete()) {
+ Log.d(TAG, "Deleted old file " + file);
+ }
+ }
+ }
+ }
+
/**
* Main thread used to handle all requests but taking screenshots.
*/
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelTest.kt
new file mode 100644
index 000000000000..288dc489c1bd
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelTest.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectValues
+import com.android.systemui.flags.Flags
+import com.android.systemui.flags.fakeFeatureFlagsClassic
+import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
+import com.android.systemui.keyguard.shared.model.TransitionStep
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@ExperimentalCoroutinesApi
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class AlternateBouncerToOccludedTransitionViewModelTest : SysuiTestCase() {
+ val kosmos =
+ testKosmos().apply {
+ fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
+ }
+
+ private val testScope = kosmos.testScope
+ private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
+ private val underTest by lazy { kosmos.alternateBouncerToOccludedTransitionViewModel }
+
+ @Test
+ fun deviceEntryParentViewDisappear() =
+ testScope.runTest {
+ val values by collectValues(underTest.deviceEntryParentViewAlpha)
+
+ keyguardTransitionRepository.sendTransitionSteps(
+ listOf(
+ step(0f, TransitionState.STARTED),
+ step(0f),
+ step(0.1f),
+ step(0.2f),
+ step(0.3f),
+ step(1f),
+ ),
+ testScope,
+ )
+
+ values.forEach { assertThat(it).isEqualTo(0f) }
+ }
+
+ private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep {
+ return TransitionStep(
+ from = KeyguardState.ALTERNATE_BOUNCER,
+ to = KeyguardState.OCCLUDED,
+ value = value,
+ transitionState = state,
+ ownerName = "AlternateBouncerToOccludedTransitionViewModelTest"
+ )
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
index e160cfc0b06e..66f741620e44 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/NotificationShadeWindowControllerImplTest.java
@@ -155,7 +155,6 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase {
mColorExtractor,
mDumpManager,
mKeyguardStateController,
- mKosmos.getScreenOffAnimationController(),
mAuthController,
mKosmos::getShadeInteractor,
mShadeWindowLogger,
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index 0bc29a8d0f16..95bc514540f5 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -123,6 +123,7 @@ import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.globalactions.domain.interactor.GlobalActionsInteractor;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
import com.android.systemui.plugins.GlobalActionsPanelPlugin;
import com.android.systemui.scrim.ScrimDrawable;
@@ -186,6 +187,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
private static final String GLOBAL_ACTION_KEY_LOGOUT = "logout";
static final String GLOBAL_ACTION_KEY_EMERGENCY = "emergency";
static final String GLOBAL_ACTION_KEY_SCREENSHOT = "screenshot";
+ static final String GLOBAL_ACTION_KEY_SYSTEM_UPDATE = "system_update";
// See NotificationManagerService#scheduleDurationReachedLocked
private static final long TOAST_FADE_TIME = 333;
@@ -213,6 +215,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
private final TelecomManager mTelecomManager;
private final MetricsLogger mMetricsLogger;
private final UiEventLogger mUiEventLogger;
+ private final ActivityStarter mActivityStarter;
// Used for RingerModeTracker
private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
@@ -317,7 +320,10 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
GA_CLOSE_TAP_OUTSIDE(810),
@UiEvent(doc = "Power menu was closed via power + volume up.")
- GA_CLOSE_POWER_VOLUP(811);
+ GA_CLOSE_POWER_VOLUP(811),
+
+ @UiEvent(doc = "System Update button was pressed.")
+ GA_SYSTEM_UPDATE_PRESS(1716);
private final int mId;
@@ -349,6 +355,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
@NonNull VibratorHelper vibrator,
@Main Resources resources,
ConfigurationController configurationController,
+ ActivityStarter activityStarter,
UserTracker userTracker,
KeyguardStateController keyguardStateController,
UserManager userManager,
@@ -385,6 +392,7 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
mSecureSettings = secureSettings;
mResources = resources;
mConfigurationController = configurationController;
+ mActivityStarter = activityStarter;
mUserTracker = userTracker;
mUserManager = userManager;
mTrustManager = trustManager;
@@ -659,6 +667,8 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
if (shouldDisplayEmergency()) {
addIfShouldShowAction(tempActions, new EmergencyDialerAction());
}
+ } else if (GLOBAL_ACTION_KEY_SYSTEM_UPDATE.equals(actionKey)) {
+ addIfShouldShowAction(tempActions, new SystemUpdateAction());
} else {
Log.e(TAG, "Invalid global action key " + actionKey);
}
@@ -1145,6 +1155,40 @@ public class GlobalActionsDialogLite implements DialogInterface.OnDismissListene
}
}
+ @VisibleForTesting
+ final class SystemUpdateAction extends SinglePressAction {
+
+ SystemUpdateAction() {
+ super(com.android.settingslib.R.drawable.ic_system_update,
+ com.android.settingslib.R.string.system_update_settings_list_item_title);
+ }
+
+ @Override
+ public void onPress() {
+ mUiEventLogger.log(GlobalActionsEvent.GA_SYSTEM_UPDATE_PRESS);
+ launchSystemUpdate();
+ }
+
+ @Override
+ public boolean showDuringKeyguard() {
+ return true;
+ }
+
+ @Override
+ public boolean showBeforeProvisioning() {
+ return false;
+ }
+
+ private void launchSystemUpdate() {
+ Intent intent = new Intent(Settings.ACTION_SYSTEM_UPDATE_SETTINGS);
+ intent.addFlags(
+ Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
+ // postStartActivityDismissingKeyguard is used for showing keyguard
+ // input/pin/password screen if lockscreen is secured, before sending the intent.
+ mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
+ }
+ }
+
private Action getSettingsAction() {
return new SinglePressAction(R.drawable.ic_settings,
R.string.global_action_settings) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index ae163eaf811f..674c128a580e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.service.dreams.Flags.dismissDreamOnKeyguardDismiss;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_APPEARING;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
@@ -89,14 +90,14 @@ import com.android.wm.shell.shared.ShellTransitions;
import com.android.wm.shell.shared.TransitionUtil;
import com.android.wm.shell.transition.Transitions;
-import kotlinx.coroutines.CoroutineScope;
-
import java.util.ArrayList;
import java.util.Map;
import java.util.WeakHashMap;
import javax.inject.Inject;
+import kotlinx.coroutines.CoroutineScope;
+
public class KeyguardService extends Service {
static final String TAG = "KeyguardService";
static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
@@ -223,6 +224,20 @@ public class KeyguardService extends Service {
initAlphaForAnimationTargets(t, apps);
initAlphaForAnimationTargets(t, wallpapers);
+ // If the keyguard is going away, hide the dream if one exists.
+ if (dismissDreamOnKeyguardDismiss()
+ && (info.getFlags() & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0) {
+ for (RemoteAnimationTarget app : apps) {
+ final boolean isDream = app.taskInfo != null
+ && app.taskInfo.getActivityType()
+ == WindowConfiguration.ACTIVITY_TYPE_DREAM;
+ if (isDream && app.mode == RemoteAnimationTarget.MODE_CLOSING) {
+ t.hide(app.leash);
+ break;
+ }
+ }
+ }
+
t.apply();
runner.onAnimationStart(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 46aec257ba39..5d31d1e0e7af 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -21,6 +21,7 @@ import static android.app.StatusBarManager.SESSION_KEYGUARD;
import static android.provider.Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT;
import static android.provider.Settings.System.LOCKSCREEN_SOUNDS_ENABLED;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static android.service.dreams.Flags.dismissDreamOnKeyguardDismiss;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_LAUNCHER_CLEAR_SNAPSHOT;
@@ -3092,13 +3093,22 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
createInteractionJankMonitorConf(
CUJ_LOCKSCREEN_UNLOCK_ANIMATION, "DismissPanel"));
+ // Filter out any closing apps, such as the dream.
+ RemoteAnimationTarget[] openingApps = apps;
+ if (dismissDreamOnKeyguardDismiss()) {
+ openingApps = Arrays.stream(apps)
+ .filter(a -> a.mode == RemoteAnimationTarget.MODE_OPENING)
+ .toArray(RemoteAnimationTarget[]::new);
+ }
+
// Pass the surface and metadata to the unlock animation controller.
RemoteAnimationTarget[] openingWallpapers = Arrays.stream(wallpapers).filter(
w -> w.mode == RemoteAnimationTarget.MODE_OPENING).toArray(
RemoteAnimationTarget[]::new);
+
mKeyguardUnlockAnimationControllerLazy.get()
.notifyStartSurfaceBehindRemoteAnimation(
- apps, openingWallpapers, startTime,
+ openingApps, openingWallpapers, startTime,
mSurfaceBehindRemoteAnimationRequested);
} else {
mInteractionJankMonitor.begin(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
index e441017c943b..5a28f7113ebd 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAlternateBouncerTransitionInteractor.kt
@@ -193,5 +193,6 @@ constructor(
val TO_AOD_DURATION = TRANSITION_DURATION_MS
val TO_PRIMARY_BOUNCER_DURATION = TRANSITION_DURATION_MS
val TO_DOZING_DURATION = TRANSITION_DURATION_MS
+ val TO_OCCLUDED_DURATION = TRANSITION_DURATION_MS
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
index 3b21141273e0..a8e9041abfd7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/transitions/DeviceEntryIconTransitionModule.kt
@@ -18,6 +18,7 @@ package com.android.systemui.keyguard.ui.transitions
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToAodTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToDozingTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToGoneTransitionViewModel
+import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToOccludedTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerToPrimaryBouncerTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToGoneTransitionViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodToLockscreenTransitionViewModel
@@ -71,6 +72,12 @@ abstract class DeviceEntryIconTransitionModule {
@Binds
@IntoSet
+ abstract fun alternateBouncerToOccluded(
+ impl: AlternateBouncerToOccludedTransitionViewModel
+ ): DeviceEntryIconTransition
+
+ @Binds
+ @IntoSet
abstract fun alternateBouncerToPrimaryBouncer(
impl: AlternateBouncerToPrimaryBouncerTransitionViewModel
): DeviceEntryIconTransition
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt
new file mode 100644
index 000000000000..27febd38a97c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModel.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.domain.interactor.FromAlternateBouncerTransitionInteractor.Companion.TO_OCCLUDED_DURATION
+import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
+import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
+import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
+import javax.inject.Inject
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * Breaks down ALTERNATE_BOUNCER->GONE transition into discrete steps for corresponding views to
+ * consume.
+ */
+@OptIn(ExperimentalCoroutinesApi::class)
+@SysUISingleton
+class AlternateBouncerToOccludedTransitionViewModel
+@Inject
+constructor(
+ animationFlow: KeyguardTransitionAnimationFlow,
+) : DeviceEntryIconTransition {
+ private val transitionAnimation =
+ animationFlow.setup(
+ duration = TO_OCCLUDED_DURATION,
+ from = ALTERNATE_BOUNCER,
+ to = KeyguardState.OCCLUDED,
+ )
+
+ override val deviceEntryParentViewAlpha: Flow<Float> =
+ transitionAnimation.immediatelyTransitionTo(0f)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
index 30f33a3a2f6f..f8086f5f6fb4 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/BackPanelController.kt
@@ -21,19 +21,20 @@ import android.graphics.Color
import android.graphics.Paint
import android.graphics.Point
import android.os.Handler
-import android.os.SystemClock
import android.util.Log
import android.util.MathUtils
import android.view.Gravity
import android.view.HapticFeedbackConstants
import android.view.MotionEvent
import android.view.VelocityTracker
+import android.view.View
import android.view.ViewConfiguration
import android.view.WindowManager
import androidx.annotation.VisibleForTesting
import androidx.core.os.postDelayed
import androidx.core.view.isVisible
import androidx.dynamicanimation.animation.DynamicAnimation
+import com.android.internal.jank.Cuj
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.util.LatencyTracker
import com.android.systemui.dagger.qualifiers.Main
@@ -41,6 +42,7 @@ import com.android.systemui.plugins.NavigationEdgeBackPlugin
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.util.ViewController
+import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import javax.inject.Inject
import kotlin.math.abs
@@ -84,6 +86,7 @@ internal constructor(
private val windowManager: WindowManager,
private val viewConfiguration: ViewConfiguration,
@Main private val mainHandler: Handler,
+ private val systemClock: SystemClock,
private val vibratorHelper: VibratorHelper,
private val configurationController: ConfigurationController,
private val latencyTracker: LatencyTracker,
@@ -102,6 +105,7 @@ internal constructor(
private val windowManager: WindowManager,
private val viewConfiguration: ViewConfiguration,
@Main private val mainHandler: Handler,
+ private val systemClock: SystemClock,
private val vibratorHelper: VibratorHelper,
private val configurationController: ConfigurationController,
private val latencyTracker: LatencyTracker,
@@ -115,6 +119,7 @@ internal constructor(
windowManager,
viewConfiguration,
mainHandler,
+ systemClock,
vibratorHelper,
configurationController,
latencyTracker,
@@ -158,9 +163,9 @@ internal constructor(
private var gestureInactiveTime = 0L
private val elapsedTimeSinceInactive
- get() = SystemClock.uptimeMillis() - gestureInactiveTime
+ get() = systemClock.uptimeMillis() - gestureInactiveTime
private val elapsedTimeSinceEntry
- get() = SystemClock.uptimeMillis() - gestureEntryTime
+ get() = systemClock.uptimeMillis() - gestureEntryTime
private var pastThresholdWhileEntryOrInactiveTime = 0L
private var entryToActiveDelay = 0F
@@ -178,7 +183,7 @@ internal constructor(
// Distance in pixels a drag can be considered for a fling event
private var minFlingDistance = 0
- private val failsafeRunnable = Runnable { onFailsafe() }
+ internal val failsafeRunnable = Runnable { onFailsafe() }
internal enum class GestureState {
/* Arrow is off the screen and invisible */
@@ -370,6 +375,7 @@ internal constructor(
// Receiving a CANCEL implies that something else intercepted
// the gesture, i.e., the user did not cancel their gesture.
// Therefore, disappear immediately, with minimum fanfare.
+ interactionJankMonitor.cancel(Cuj.CUJ_BACK_PANEL_ARROW)
updateArrowState(GestureState.GONE)
velocityTracker = null
}
@@ -692,10 +698,10 @@ internal constructor(
}
if (isPastThresholdForFirstTime) {
- pastThresholdWhileEntryOrInactiveTime = SystemClock.uptimeMillis()
+ pastThresholdWhileEntryOrInactiveTime = systemClock.uptimeMillis()
entryToActiveDelay = dynamicDelay()
}
- val timePastThreshold = SystemClock.uptimeMillis() - pastThresholdWhileEntryOrInactiveTime
+ val timePastThreshold = systemClock.uptimeMillis() - pastThresholdWhileEntryOrInactiveTime
return timePastThreshold > entryToActiveDelay
}
@@ -881,6 +887,16 @@ internal constructor(
previousState = currentState
currentState = newState
+ // First, update the jank tracker
+ when (currentState) {
+ GestureState.ENTRY -> {
+ interactionJankMonitor.cancel(Cuj.CUJ_BACK_PANEL_ARROW)
+ interactionJankMonitor.begin(mView, Cuj.CUJ_BACK_PANEL_ARROW)
+ }
+ GestureState.GONE -> interactionJankMonitor.end(Cuj.CUJ_BACK_PANEL_ARROW)
+ else -> {}
+ }
+
when (currentState) {
GestureState.CANCELLED -> {
backCallback.cancelBack()
@@ -912,7 +928,7 @@ internal constructor(
mView.isVisible = true
updateRestingArrowDimens()
- gestureEntryTime = SystemClock.uptimeMillis()
+ gestureEntryTime = systemClock.uptimeMillis()
}
GestureState.ACTIVE -> {
previousXTranslationOnActiveOffset = previousXTranslation
@@ -927,7 +943,7 @@ internal constructor(
mView.popOffEdge(popVelocity)
}
GestureState.INACTIVE -> {
- gestureInactiveTime = SystemClock.uptimeMillis()
+ gestureInactiveTime = systemClock.uptimeMillis()
// Typically entering INACTIVE means
// totalTouchDelta <= deactivationSwipeTriggerThreshold
@@ -1041,6 +1057,11 @@ internal constructor(
pw.println(" isLeftPanel=${mView.isLeftPanel}")
}
+ @VisibleForTesting
+ internal fun getBackPanelView(): BackPanel {
+ return mView
+ }
+
init {
if (DEBUG)
mView.drawDebugInfo = { canvas ->
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
index 8b7e11c4ab47..4a636d28aa88 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowControllerImpl.java
@@ -68,7 +68,6 @@ import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -131,7 +130,6 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
mCallbacks = new ArrayList<>();
private final SysuiColorExtractor mColorExtractor;
- private final ScreenOffAnimationController mScreenOffAnimationController;
/**
* Layout params would be aggregated and dispatched all at once if this is > 0.
*
@@ -159,7 +157,6 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
SysuiColorExtractor colorExtractor,
DumpManager dumpManager,
KeyguardStateController keyguardStateController,
- ScreenOffAnimationController screenOffAnimationController,
AuthController authController,
Lazy<ShadeInteractor> shadeInteractorLazy,
ShadeWindowLogger logger,
@@ -179,7 +176,6 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
mKeyguardBypassController = keyguardBypassController;
mBackgroundExecutor = backgroundExecutor;
mColorExtractor = colorExtractor;
- mScreenOffAnimationController = screenOffAnimationController;
// prefix with {slow} to make sure this dumps at the END of the critical section.
dumpManager.registerCriticalDumpable("{slow}NotificationShadeWindowControllerImpl", this);
mAuthController = authController;
@@ -441,14 +437,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
private void applyFocusableFlag(NotificationShadeWindowState state) {
boolean panelFocusable = state.notificationShadeFocusable && state.shadeOrQsExpanded;
if (state.bouncerShowing && (state.keyguardOccluded || state.keyguardNeedsInput)
- || ENABLE_REMOTE_INPUT && state.remoteInputActive
- // Make the panel focusable if we're doing the screen off animation, since the light
- // reveal scrim is drawing in the panel and should consume touch events so that they
- // don't go to the app behind.
- || mScreenOffAnimationController.shouldIgnoreKeyguardTouches()) {
- mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
- mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
- } else if (state.glanceableHubShowing) {
+ || (ENABLE_REMOTE_INPUT && state.remoteInputActive)
+ || state.glanceableHubShowing) {
mLpChanged.flags &= ~LayoutParams.FLAG_NOT_FOCUSABLE;
mLpChanged.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
} else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
index 77b30402c040..cfe37eef1f87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
@@ -67,6 +67,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.globalactions.domain.interactor.GlobalActionsInteractor;
import com.android.systemui.kosmos.KosmosJavaAdapter;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.GlobalActions;
import com.android.systemui.settings.UserContextProvider;
import com.android.systemui.settings.UserTracker;
@@ -114,6 +115,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
private SecureSettings mSecureSettings;
@Mock private Resources mResources;
@Mock private ConfigurationController mConfigurationController;
+ @Mock private ActivityStarter mActivityStarter;
@Mock private UserTracker mUserTracker;
@Mock private KeyguardStateController mKeyguardStateController;
@Mock private UserManager mUserManager;
@@ -173,6 +175,7 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
mVibratorHelper,
mResources,
mConfigurationController,
+ mActivityStarter,
mUserTracker,
mKeyguardStateController,
mUserManager,
@@ -458,6 +461,18 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
}
}
+ private static <T> void assertNoItemsOfType(List<T> stuff, Class<? extends T> klass) {
+ for (int i = 0; i < stuff.size(); i++) {
+ assertThat(stuff.get(i)).isNotInstanceOf(klass);
+ }
+ }
+
+ private static <T> void assertOneItemOfType(List<T> stuff, Class<? extends T> klass) {
+ List<?> classes = stuff.stream().map((item) -> item.getClass()).toList();
+ assertThat(classes).containsNoDuplicates();
+ assertThat(classes).contains(klass);
+ }
+
@Test
public void testCreateActionItems_lockdownEnabled_doesShowLockdown() {
mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
@@ -641,6 +656,113 @@ public class GlobalActionsDialogLiteTest extends SysuiTestCase {
assertThat(mInteractor.isVisible().getValue()).isFalse();
}
+ @Test
+ public void testShouldLogSystemUpdatePress() {
+ GlobalActionsDialogLite.SystemUpdateAction systemUpdateAction =
+ mGlobalActionsDialogLite.new SystemUpdateAction();
+ systemUpdateAction.onPress();
+ verifyLogPosted(GlobalActionsDialogLite.GlobalActionsEvent.GA_SYSTEM_UPDATE_PRESS);
+ }
+
+ @Test
+ public void testCreateActionItems_systemUpdateEnabled_doesShowSystemUpdate() {
+ mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
+ doReturn(5).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayEmergency();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
+ doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
+ String[] actions = {
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_SYSTEM_UPDATE
+ };
+ doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
+ mGlobalActionsDialogLite.createActionItems();
+
+ assertItemsOfType(mGlobalActionsDialogLite.mItems,
+ GlobalActionsDialogLite.EmergencyAction.class,
+ GlobalActionsDialogLite.LockDownAction.class,
+ GlobalActionsDialogLite.ShutDownAction.class,
+ GlobalActionsDialogLite.RestartAction.class,
+ GlobalActionsDialogLite.SystemUpdateAction.class);
+ assertThat(mGlobalActionsDialogLite.mOverflowItems).isEmpty();
+ assertThat(mGlobalActionsDialogLite.mPowerItems).isEmpty();
+ }
+
+ @Test
+ public void testCreateActionItems_systemUpdateDisabled_doesntShowSystemUpdateAction() {
+ mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
+ doReturn(5).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayEmergency();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
+ doReturn(true).when(mGlobalActionsDialogLite).shouldShowAction(any());
+ String[] actions = {
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART
+ };
+ doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
+ mGlobalActionsDialogLite.createActionItems();
+
+ assertNoItemsOfType(mGlobalActionsDialogLite.mItems,
+ GlobalActionsDialogLite.SystemUpdateAction.class);
+ assertThat(mGlobalActionsDialogLite.mOverflowItems).isEmpty();
+ assertThat(mGlobalActionsDialogLite.mPowerItems).isEmpty();
+ }
+
+ @Test
+ public void testCreateActionItems_systemUpdateEnabled_locked_showsSystemUpdate() {
+ mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
+ doReturn(5).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayEmergency();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
+ String[] actions = {
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_SYSTEM_UPDATE
+ };
+ doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
+
+ // Show dialog with keyguard showing
+ mGlobalActionsDialogLite.showOrHideDialog(true, true, null);
+
+ assertOneItemOfType(mGlobalActionsDialogLite.mItems,
+ GlobalActionsDialogLite.SystemUpdateAction.class);
+
+ // Hide dialog
+ mGlobalActionsDialogLite.showOrHideDialog(true, true, null);
+ }
+
+ @Test
+ public void testCreateActionItems_systemUpdateEnabled_notProvisioned_noSystemUpdate() {
+ mGlobalActionsDialogLite = spy(mGlobalActionsDialogLite);
+ doReturn(5).when(mGlobalActionsDialogLite).getMaxShownPowerItems();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayEmergency();
+ doReturn(true).when(mGlobalActionsDialogLite).shouldDisplayLockdown(any());
+ String[] actions = {
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_EMERGENCY,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_LOCKDOWN,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_POWER,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_RESTART,
+ GlobalActionsDialogLite.GLOBAL_ACTION_KEY_SYSTEM_UPDATE
+ };
+ doReturn(actions).when(mGlobalActionsDialogLite).getDefaultActions();
+
+ // Show dialog with keyguard showing
+ mGlobalActionsDialogLite.showOrHideDialog(false, false, null);
+
+ assertNoItemsOfType(mGlobalActionsDialogLite.mItems,
+ GlobalActionsDialogLite.SystemUpdateAction.class);
+
+ // Hide dialog
+ mGlobalActionsDialogLite.showOrHideDialog(false, false, null);
+ }
+
private UserInfo mockCurrentUser(int flags) {
return new UserInfo(10, "A User", flags);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index 59f7d613c1e6..325e7bf31a43 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -262,7 +262,6 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
mColorExtractor,
mDumpManager,
mKeyguardStateController,
- mScreenOffAnimationController,
mAuthController,
() -> mShadeInteractor,
mShadeWindowLogger,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
index e6c259abb456..f1c97dd45f09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/gestural/BackPanelControllerTest.kt
@@ -17,7 +17,6 @@
package com.android.systemui.navigationbar.gestural
import android.os.Handler
-import android.os.Looper
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.view.HapticFeedbackConstants
@@ -28,6 +27,7 @@ import android.view.MotionEvent.ACTION_UP
import android.view.ViewConfiguration
import android.view.WindowManager
import androidx.test.filters.SmallTest
+import com.android.internal.jank.Cuj
import com.android.internal.util.LatencyTracker
import com.android.systemui.SysuiTestCase
import com.android.systemui.jank.interactionJankMonitor
@@ -35,6 +35,7 @@ import com.android.systemui.plugins.NavigationEdgeBackPlugin
import com.android.systemui.statusbar.VibratorHelper
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.testKosmos
+import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
@@ -43,6 +44,7 @@ import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -55,6 +57,7 @@ class BackPanelControllerTest : SysuiTestCase() {
}
private val kosmos = testKosmos()
private lateinit var mBackPanelController: BackPanelController
+ private lateinit var systemClock: FakeSystemClock
private lateinit var testableLooper: TestableLooper
private var triggerThreshold: Float = 0.0f
private val touchSlop = ViewConfiguration.get(context).scaledEdgeSlop
@@ -69,12 +72,15 @@ class BackPanelControllerTest : SysuiTestCase() {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
+ testableLooper = TestableLooper.get(this)
+ systemClock = FakeSystemClock()
mBackPanelController =
BackPanelController(
context,
windowManager,
ViewConfiguration.get(context),
- Handler.createAsync(checkNotNull(Looper.myLooper())),
+ Handler.createAsync(testableLooper.looper),
+ systemClock,
vibratorHelper,
configurationController,
latencyTracker,
@@ -83,7 +89,6 @@ class BackPanelControllerTest : SysuiTestCase() {
mBackPanelController.setLayoutParams(layoutParams)
mBackPanelController.setBackCallback(backCallback)
mBackPanelController.setIsLeftPanel(true)
- testableLooper = TestableLooper.get(this)
triggerThreshold = mBackPanelController.params.staticTriggerThreshold
}
@@ -103,6 +108,7 @@ class BackPanelControllerTest : SysuiTestCase() {
assertThat(mBackPanelController.currentState)
.isEqualTo(BackPanelController.GestureState.GONE)
+ verify(interactionJankMonitor, never()).begin(any())
}
@Test
@@ -110,23 +116,37 @@ class BackPanelControllerTest : SysuiTestCase() {
startTouch()
// Move once to cross the touch slop
continueTouch(START_X + touchSlop.toFloat() + 1)
+ assertThat(mBackPanelController.currentState)
+ .isEqualTo(BackPanelController.GestureState.ENTRY)
+ verify(interactionJankMonitor).cancel(Cuj.CUJ_BACK_PANEL_ARROW)
+ verify(interactionJankMonitor)
+ .begin(mBackPanelController.getBackPanelView(), Cuj.CUJ_BACK_PANEL_ARROW)
// Move again to cross the back trigger threshold
continueTouch(START_X + touchSlop + triggerThreshold + 1)
// Wait threshold duration and hold touch past trigger threshold
- Thread.sleep((MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION + 1).toLong())
+ moveTimeForward((MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION + 1).toLong())
continueTouch(START_X + touchSlop + triggerThreshold + 1)
assertThat(mBackPanelController.currentState)
.isEqualTo(BackPanelController.GestureState.ACTIVE)
verify(backCallback).setTriggerBack(true)
- testableLooper.moveTimeForward(100)
- testableLooper.processAllMessages()
+ moveTimeForward(100)
verify(vibratorHelper)
.performHapticFeedback(any(), eq(HapticFeedbackConstants.GESTURE_THRESHOLD_ACTIVATE))
finishTouchActionUp(START_X + touchSlop + triggerThreshold + 1)
assertThat(mBackPanelController.currentState)
.isEqualTo(BackPanelController.GestureState.COMMITTED)
verify(backCallback).triggerBack()
+
+ // Because the Handler that is typically used for transitioning the arrow state from
+ // COMMITTED to GONE is used as an animation-end-listener on a SpringAnimation,
+ // there is no way to meaningfully test that the state becomes GONE and that the tracked
+ // jank interaction is ended. So instead, manually trigger the failsafe, which does
+ // the same thing:
+ mBackPanelController.failsafeRunnable.run()
+ assertThat(mBackPanelController.currentState)
+ .isEqualTo(BackPanelController.GestureState.GONE)
+ verify(interactionJankMonitor).end(Cuj.CUJ_BACK_PANEL_ARROW)
}
@Test
@@ -134,19 +154,22 @@ class BackPanelControllerTest : SysuiTestCase() {
startTouch()
// Move once to cross the touch slop
continueTouch(START_X + touchSlop.toFloat() + 1)
+ assertThat(mBackPanelController.currentState)
+ .isEqualTo(BackPanelController.GestureState.ENTRY)
// Move again to cross the back trigger threshold
continueTouch(
START_X + touchSlop + triggerThreshold -
mBackPanelController.params.deactivationTriggerThreshold
)
// Wait threshold duration and hold touch before trigger threshold
- Thread.sleep((MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION + 1).toLong())
+ moveTimeForward((MAX_DURATION_ENTRY_BEFORE_ACTIVE_ANIMATION + 1).toLong())
continueTouch(
START_X + touchSlop + triggerThreshold -
mBackPanelController.params.deactivationTriggerThreshold
)
clearInvocations(backCallback)
- Thread.sleep(MIN_DURATION_ACTIVE_BEFORE_INACTIVE_ANIMATION)
+ moveTimeForward(MIN_DURATION_ACTIVE_BEFORE_INACTIVE_ANIMATION)
+
// Move in the opposite direction to cross the deactivation threshold and cancel back
continueTouch(START_X)
@@ -175,4 +198,10 @@ class BackPanelControllerTest : SysuiTestCase() {
private fun createMotionEvent(action: Int, x: Float, y: Float): MotionEvent {
return MotionEvent.obtain(0L, 0L, action, x, y, 0)
}
+
+ private fun moveTimeForward(millis: Long) {
+ systemClock.advanceTime(millis)
+ testableLooper.moveTimeForward(millis)
+ testableLooper.processAllMessages()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index db998f3b5cd8..2017954c6b34 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -338,8 +338,6 @@ public class BubblesTest extends SysuiTestCase {
@Mock
private KeyguardStateController mKeyguardStateController;
@Mock
- private ScreenOffAnimationController mScreenOffAnimationController;
- @Mock
Transitions mTransitions;
@Mock
private Optional<OneHandedController> mOneHandedOptional;
@@ -491,7 +489,6 @@ public class BubblesTest extends SysuiTestCase {
mColorExtractor,
mDumpManager,
mKeyguardStateController,
- mScreenOffAnimationController,
mAuthController,
() -> mShadeInteractor,
mShadeWindowLogger,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelKosmos.kt
new file mode 100644
index 000000000000..71ad3c6689f7
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerToOccludedTransitionViewModelKosmos.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.keyguard.ui.viewmodel
+
+import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.Kosmos.Fixture
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+
+val Kosmos.alternateBouncerToOccludedTransitionViewModel by Fixture {
+ AlternateBouncerToOccludedTransitionViewModel(
+ animationFlow = keyguardTransitionAnimationFlow,
+ )
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
index d4b793720328..a81ac038b38a 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/kosmos/KosmosJavaAdapter.kt
@@ -56,7 +56,6 @@ import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.shadeController
import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor
-import com.android.systemui.statusbar.phone.screenOffAnimationController
import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository
import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
@@ -90,7 +89,6 @@ class KosmosJavaAdapter(
val simBouncerInteractor by lazy { kosmos.simBouncerInteractor }
val statusBarStateController by lazy { kosmos.statusBarStateController }
val interactionJankMonitor by lazy { kosmos.interactionJankMonitor }
- val screenOffAnimationController by lazy { kosmos.screenOffAnimationController }
val fakeSceneContainerConfig by lazy { kosmos.sceneContainerConfig }
val sceneInteractor by lazy { kosmos.sceneInteractor }
val falsingCollector by lazy { kosmos.falsingCollector }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 2d1aba4b43aa..bc83a0edd918 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2691,7 +2691,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
for (Record r : mRecords) {
if (r.matchTelephonyCallbackEvent(
TelephonyCallback.EVENT_RADIO_POWER_STATE_CHANGED)
- && idMatch(r, subId, phoneId)) {
+ && idMatchRelaxed(r, subId, phoneId)) {
try {
r.callback.onRadioPowerStateChanged(state);
} catch (RemoteException ex) {
@@ -4089,6 +4089,45 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
+ /**
+ * Match the sub id or phone id of the event to the record with relaxed rules
+ *
+ * We follow the rules below:
+ * 1) If sub id of the event is invalid, phone id should be used.
+ * 2) If record's phoneId is also invalid then allow phone 0 notifications
+ * 3) The event on default sub should be notified to the records
+ * which register the default sub id.
+ * 4) Sub id should be exactly matched for all other cases.
+ * TODO: b/337878785 for longterm fix
+ */
+ boolean idMatchRelaxed(Record r, int subId, int phoneId) {
+ if (!Flags.useRelaxedIdMatch()) {
+ return idMatch(r, subId, phoneId);
+ }
+
+ if (subId < 0) {
+ // Invalid case, we need compare phoneId.
+ // If the record does not have a valid phone Id send phone 0 notifications.
+ // A record's phoneId can get invalid if there is no SIM or modem was restarting
+ // when caller registered.
+ if (r.phoneId == INVALID_SIM_SLOT_INDEX) {
+ return (phoneId == 0);
+ } else {
+ return (r.phoneId == phoneId);
+ }
+ }
+
+ if (r.subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) {
+ // if the registered record does not have a valid phoneId then use the phone 0
+ if (r.phoneId == INVALID_SIM_SLOT_INDEX) {
+ return (phoneId == 0);
+ }
+ return (subId == mDefaultSubId);
+ } else {
+ return (r.subId == subId);
+ }
+ }
+
private boolean checkFineLocationAccess(Record r) {
return checkFineLocationAccess(r, Build.VERSION_CODES.BASE);
}
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index b7030765d053..c6c1f9873a45 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -155,9 +155,6 @@ import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
@@ -225,9 +222,18 @@ class UserController implements Handler.Callback {
private static final int USER_SWITCH_CALLBACKS_TIMEOUT_MS = 5 * 1000;
/**
+ * Amount of time waited for
+ * {@link ActivityTaskManagerInternal.ScreenObserver#onKeyguardStateChanged} callbacks to be
+ * called after calling {@link WindowManagerService#lockDeviceNow}.
+ * Otherwise, we should throw a {@link RuntimeException} and never dismiss the
+ * {@link UserSwitchingDialog}.
+ */
+ static final int SHOW_KEYGUARD_TIMEOUT_MS = 20 * 1000;
+
+ /**
* Amount of time waited for {@link WindowManagerService#dismissKeyguard} callbacks to be
* called after dismissing the keyguard.
- * Otherwise, we should move on to dismiss the dialog {@link #dismissUserSwitchDialog()}
+ * Otherwise, we should move on to dismiss the dialog {@link #dismissUserSwitchDialog}}
* and report user switch is complete {@link #REPORT_USER_SWITCH_COMPLETE_MSG}.
*/
private static final int DISMISS_KEYGUARD_TIMEOUT_MS = 2 * 1000;
@@ -1925,15 +1931,8 @@ class UserController implements Handler.Callback {
updateProfileRelatedCaches();
mInjector.getWindowManager().setCurrentUser(userId);
mInjector.reportCurWakefulnessUsageEvent();
- // Once the internal notion of the active user has switched, we lock the device
- // with the option to show the user switcher on the keyguard.
if (userSwitchUiEnabled) {
mInjector.getWindowManager().setSwitchingUser(true);
- // Only lock if the user has a secure keyguard PIN/Pattern/Pwd
- if (mInjector.getKeyguardManager().isDeviceSecure(userId)) {
- // Make sure the device is locked before moving on with the user switch
- mInjector.lockDeviceNowAndWaitForKeyguardShown();
- }
}
} else {
@@ -2516,34 +2515,56 @@ class UserController implements Handler.Callback {
@VisibleForTesting
void completeUserSwitch(int oldUserId, int newUserId) {
- final boolean isUserSwitchUiEnabled = isUserSwitchUiEnabled();
- // serialize each conditional step
- await(
- // STEP 1 - If there is no challenge set, dismiss the keyguard right away
- isUserSwitchUiEnabled && !mInjector.getKeyguardManager().isDeviceSecure(newUserId),
- mInjector::dismissKeyguard,
- () -> await(
- // STEP 2 - If user switch ui was enabled, dismiss user switch dialog
- isUserSwitchUiEnabled,
- this::dismissUserSwitchDialog,
- () -> {
- // STEP 3 - Send REPORT_USER_SWITCH_COMPLETE_MSG to broadcast
- // ACTION_USER_SWITCHED & call UserSwitchObservers.onUserSwitchComplete
- mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
- mHandler.sendMessage(mHandler.obtainMessage(
- REPORT_USER_SWITCH_COMPLETE_MSG, oldUserId, newUserId));
- }
- ));
- }
-
- private void await(boolean condition, Consumer<Runnable> conditionalStep, Runnable nextStep) {
- if (condition) {
- conditionalStep.accept(nextStep);
+ final Runnable sendUserSwitchCompleteMessage = () -> {
+ mHandler.removeMessages(REPORT_USER_SWITCH_COMPLETE_MSG);
+ mHandler.sendMessage(mHandler.obtainMessage(
+ REPORT_USER_SWITCH_COMPLETE_MSG, oldUserId, newUserId));
+ };
+ if (isUserSwitchUiEnabled()) {
+ if (mInjector.getKeyguardManager().isDeviceSecure(newUserId)) {
+ this.showKeyguard(() -> dismissUserSwitchDialog(sendUserSwitchCompleteMessage));
+ } else {
+ this.dismissKeyguard(() -> dismissUserSwitchDialog(sendUserSwitchCompleteMessage));
+ }
} else {
- nextStep.run();
+ sendUserSwitchCompleteMessage.run();
}
}
+ protected void showKeyguard(Runnable runnable) {
+ runWithTimeout(mInjector::showKeyguard, SHOW_KEYGUARD_TIMEOUT_MS, runnable, () -> {
+ throw new RuntimeException(
+ "Keyguard is not shown in " + SHOW_KEYGUARD_TIMEOUT_MS + " ms.");
+ }, "showKeyguard");
+ }
+
+ protected void dismissKeyguard(Runnable runnable) {
+ runWithTimeout(mInjector::dismissKeyguard, DISMISS_KEYGUARD_TIMEOUT_MS, runnable, runnable,
+ "dismissKeyguard");
+ }
+
+ private void runWithTimeout(Consumer<Runnable> task, int timeoutMs, Runnable onSuccess,
+ Runnable onTimeout, String traceMsg) {
+ final AtomicInteger state = new AtomicInteger(0); // state = 0 (RUNNING)
+
+ asyncTraceBegin(traceMsg, 0);
+
+ mHandler.postDelayed(() -> {
+ if (state.compareAndSet(0, 1)) { // state = 1 (TIMEOUT)
+ asyncTraceEnd(traceMsg, 0);
+ Slogf.w(TAG, "Timeout: %s did not finish in %d ms", traceMsg, timeoutMs);
+ onTimeout.run();
+ }
+ }, timeoutMs);
+
+ task.accept(() -> {
+ if (state.compareAndSet(0, 2)) { // state = 2 (SUCCESS)
+ asyncTraceEnd(traceMsg, 0);
+ onSuccess.run();
+ }
+ });
+ }
+
private void moveUserToForeground(UserState uss, int newUserId) {
boolean homeInFront = mInjector.taskSupervisorSwitchUser(newUserId, uss);
if (homeInFront) {
@@ -3977,29 +3998,45 @@ class UserController implements Handler.Callback {
return IStorageManager.Stub.asInterface(ServiceManager.getService("mount"));
}
- protected void dismissKeyguard(Runnable runnable) {
- final AtomicBoolean isFirst = new AtomicBoolean(true);
- final Runnable runOnce = () -> {
- if (isFirst.getAndSet(false)) {
- runnable.run();
- }
- };
+ protected void showKeyguard(Runnable runnable) {
+ if (getWindowManager().isKeyguardLocked()) {
+ runnable.run();
+ return;
+ }
+ getActivityTaskManagerInternal().registerScreenObserver(
+ new ActivityTaskManagerInternal.ScreenObserver() {
+ @Override
+ public void onAwakeStateChanged(boolean isAwake) {
+
+ }
+
+ @Override
+ public void onKeyguardStateChanged(boolean isShowing) {
+ if (isShowing) {
+ getActivityTaskManagerInternal().unregisterScreenObserver(this);
+ runnable.run();
+ }
+ }
+ }
+ );
+ getWindowManager().lockDeviceNow();
+ }
- mHandler.postDelayed(runOnce, DISMISS_KEYGUARD_TIMEOUT_MS);
+ protected void dismissKeyguard(Runnable runnable) {
getWindowManager().dismissKeyguard(new IKeyguardDismissCallback.Stub() {
@Override
public void onDismissError() throws RemoteException {
- mHandler.post(runOnce);
+ runnable.run();
}
@Override
public void onDismissSucceeded() throws RemoteException {
- mHandler.post(runOnce);
+ runnable.run();
}
@Override
public void onDismissCancelled() throws RemoteException {
- mHandler.post(runOnce);
+ runnable.run();
}
}, /* message= */ null);
}
@@ -4025,43 +4062,5 @@ class UserController implements Handler.Callback {
void onSystemUserVisibilityChanged(boolean visible) {
getUserManagerInternal().onSystemUserVisibilityChanged(visible);
}
-
- void lockDeviceNowAndWaitForKeyguardShown() {
- if (getWindowManager().isKeyguardLocked()) {
- return;
- }
-
- final TimingsTraceAndSlog t = new TimingsTraceAndSlog();
- t.traceBegin("lockDeviceNowAndWaitForKeyguardShown");
-
- final CountDownLatch latch = new CountDownLatch(1);
- ActivityTaskManagerInternal.ScreenObserver screenObserver =
- new ActivityTaskManagerInternal.ScreenObserver() {
- @Override
- public void onAwakeStateChanged(boolean isAwake) {
-
- }
-
- @Override
- public void onKeyguardStateChanged(boolean isShowing) {
- if (isShowing) {
- latch.countDown();
- }
- }
- };
-
- getActivityTaskManagerInternal().registerScreenObserver(screenObserver);
- getWindowManager().lockDeviceNow();
- try {
- if (!latch.await(20, TimeUnit.SECONDS)) {
- throw new RuntimeException("Keyguard is not shown in 20 seconds");
- }
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- } finally {
- getActivityTaskManagerInternal().unregisterScreenObserver(screenObserver);
- t.traceEnd();
- }
- }
}
}
diff --git a/services/core/java/com/android/server/audio/AudioManagerShellCommand.java b/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
index e330ed56239b..d669c8d4656f 100644
--- a/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
+++ b/services/core/java/com/android/server/audio/AudioManagerShellCommand.java
@@ -22,7 +22,10 @@ import static android.media.AudioManager.ADJUST_RAISE;
import static android.media.AudioManager.ADJUST_UNMUTE;
import android.content.Context;
+import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceVolumeManager;
import android.media.AudioManager;
+import android.media.VolumeInfo;
import android.os.ShellCommand;
import java.io.PrintWriter;
@@ -60,6 +63,8 @@ class AudioManagerShellCommand extends ShellCommand {
return resetSoundDoseTimeout();
case "set-volume":
return setVolume();
+ case "set-device-volume":
+ return setDeviceVolume();
case "adj-mute":
return adjMute();
case "adj-unmute":
@@ -97,6 +102,8 @@ class AudioManagerShellCommand extends ShellCommand {
pw.println(" Resets the sound dose timeout used for momentary exposure");
pw.println(" set-volume STREAM_TYPE VOLUME_INDEX");
pw.println(" Sets the volume for STREAM_TYPE to VOLUME_INDEX");
+ pw.println(" set-device-volume STREAM_TYPE VOLUME_INDEX NATIVE_DEVICE_TYPE");
+ pw.println(" Sets for NATIVE_DEVICE_TYPE the STREAM_TYPE volume to VOLUME_INDEX");
pw.println(" adj-mute STREAM_TYPE");
pw.println(" mutes the STREAM_TYPE");
pw.println(" adj-unmute STREAM_TYPE");
@@ -257,6 +264,23 @@ class AudioManagerShellCommand extends ShellCommand {
return 0;
}
+ private int setDeviceVolume() {
+ final Context context = mService.mContext;
+ final AudioDeviceVolumeManager advm = (AudioDeviceVolumeManager) context.getSystemService(
+ Context.AUDIO_DEVICE_VOLUME_SERVICE);
+ final int stream = readIntArg();
+ final int index = readIntArg();
+ final int device = readIntArg();
+
+ final VolumeInfo volume = new VolumeInfo.Builder(stream).setVolumeIndex(index).build();
+ final AudioDeviceAttributes ada = new AudioDeviceAttributes(
+ /*native type*/ device, /*address*/ "foo");
+ getOutPrintWriter().println(
+ "calling AudioDeviceVolumeManager.setDeviceVolume(" + volume + ", " + ada + ")");
+ advm.setDeviceVolume(volume, ada);
+ return 0;
+ }
+
private int adjMute() {
final Context context = mService.mContext;
final AudioManager am = context.getSystemService(AudioManager.class);
diff --git a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
index a5939e924adb..a439f16e6d97 100644
--- a/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
+++ b/services/core/java/com/android/server/location/gnss/GnssConfiguration.java
@@ -386,7 +386,7 @@ public class GnssConfiguration {
configs = CarrierConfigManager.getDefaultConfig();
}
for (String configKey : configs.keySet()) {
- if (configKey.startsWith(CarrierConfigManager.Gps.KEY_PREFIX)) {
+ if (configKey != null && configKey.startsWith(CarrierConfigManager.Gps.KEY_PREFIX)) {
String key = configKey
.substring(CarrierConfigManager.Gps.KEY_PREFIX.length())
.toUpperCase(Locale.ROOT);
diff --git a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
index 8002300dacc0..880787e8664c 100644
--- a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
+++ b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java
@@ -203,7 +203,7 @@ class GnssNetworkConnectivityHandler {
SubscriptionManager subManager = mContext.getSystemService(SubscriptionManager.class);
if (subManager != null) {
- if (Flags.subscriptionsListenerThread()) {
+ if (Flags.subscriptionsChangedListenerThread()) {
subManager.addOnSubscriptionsChangedListener(FgThread.getExecutor(),
mOnSubscriptionsChangeListener);
} else {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bff3d39d7361..9d4ab11d7001 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -266,7 +266,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.WorkSource;
import android.permission.PermissionManager;
-import android.provider.DeviceConfig;
import android.provider.Settings;
import android.provider.Settings.Secure;
import android.service.notification.Adjustment;
@@ -313,7 +312,6 @@ import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.compat.IPlatformCompat;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags;
import com.android.internal.config.sysui.SystemUiSystemPropertiesFlags.NotificationFlags;
import com.android.internal.logging.InstanceId;
@@ -704,7 +702,6 @@ public class NotificationManagerService extends SystemService {
private ConditionProviders mConditionProviders;
private NotificationUsageStats mUsageStats;
private boolean mLockScreenAllowSecureNotifications = true;
- boolean mSystemExemptFromDismissal = false;
final ArrayMap<String, ArrayMap<Integer,
RemoteCallbackList<ICallNotificationEventCallback>>>
mCallNotificationEventCallbacks = new ArrayMap<>();
@@ -722,7 +719,6 @@ public class NotificationManagerService extends SystemService {
private GroupHelper mGroupHelper;
private int mAutoGroupAtCount;
private boolean mIsTelevision;
- private DeviceConfig.OnPropertiesChangedListener mDeviceConfigChangedListener;
protected NotificationAttentionHelper mAttentionHelper;
private int mWarnRemoteViewsSizeBytes;
@@ -973,18 +969,6 @@ public class NotificationManagerService extends SystemService {
}
protected void setDefaultAssistantForUser(int userId) {
- String overrideDefaultAssistantString = DeviceConfig.getProperty(
- DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE);
- if (overrideDefaultAssistantString != null) {
- ArraySet<ComponentName> approved = mAssistants.queryPackageForServices(
- overrideDefaultAssistantString,
- MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE,
- userId);
- for (int i = 0; i < approved.size(); i++) {
- if (allowAssistant(userId, approved.valueAt(i))) return;
- }
- }
ArraySet<ComponentName> defaults = mAssistants.getDefaultComponents();
// We should have only one default assistant by default
// allowAssistant should execute once in practice
@@ -2670,10 +2654,6 @@ public class NotificationManagerService extends SystemService {
mStatsManager.clearPullAtomCallback(DND_MODE_RULE);
mAppOps.stopWatchingMode(mAppOpsListener);
mAlarmManager.cancelAll();
-
- if (mDeviceConfigChangedListener != null) {
- DeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigChangedListener);
- }
}
protected String[] getStringArrayResource(int key) {
@@ -2744,27 +2724,6 @@ public class NotificationManagerService extends SystemService {
publishLocalService(NotificationManagerInternal.class, mInternalService);
}
- void registerDeviceConfigChange() {
- mDeviceConfigChangedListener = properties -> {
- if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(properties.getNamespace())) {
- return;
- }
- for (String name : properties.getKeyset()) {
- if (SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE.equals(name)) {
- mAssistants.resetDefaultAssistantsIfNecessary();
- }
- }
- };
- mSystemExemptFromDismissal = DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
- /* name= */ "application_exemptions",
- /* defaultValue= */ true);
- DeviceConfig.addOnPropertiesChangedListener(
- DeviceConfig.NAMESPACE_SYSTEMUI,
- new HandlerExecutor(mHandler),
- mDeviceConfigChangedListener);
- }
-
private void registerNotificationPreferencesPullers() {
mPullAtomCallback = new StatsPullAtomCallbackImpl();
mStatsManager.setPullAtomCallback(
@@ -2938,7 +2897,6 @@ public class NotificationManagerService extends SystemService {
mAssistants.onBootPhaseAppsCanStart();
mConditionProviders.onBootPhaseAppsCanStart();
mHistoryManager.onBootPhaseAppsCanStart();
- registerDeviceConfigChange();
migrateDefaultNAS();
maybeShowInitialReviewPermissionsNotification();
@@ -7738,7 +7696,7 @@ public class NotificationManagerService extends SystemService {
return true;
}
// Check if an app has been given system exemption
- return mSystemExemptFromDismissal && mAppOps.checkOpNoThrow(
+ return mAppOps.checkOpNoThrow(
AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid,
ai.packageName) == MODE_ALLOWED;
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b41755b71fb5..1f320dab99dd 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -4105,6 +4105,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean removedFromHistory = false;
cleanUp(false /* cleanServices */, false /* setState */);
+ setVisibleRequested(false);
if (hasProcess()) {
app.removeActivity(this, true /* keepAssociation */);
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index f04b4af285be..8069a9335151 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -48,8 +48,15 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
/**
* Flag to indicate whether to restrict desktop mode to supported devices.
*/
+ @VisibleForTesting
+ static final String ENFORCE_DEVICE_RESTRICTIONS_KEY =
+ "persist.wm.debug.desktop_mode_enforce_device_restrictions";
+
+ /**
+ * Flag to indicate whether to restrict desktop mode to supported devices.
+ */
private static final boolean ENFORCE_DEVICE_RESTRICTIONS = SystemProperties.getBoolean(
- "persist.wm.debug.desktop_mode_enforce_device_restrictions", true);
+ ENFORCE_DEVICE_RESTRICTIONS_KEY, true);
private StringBuilder mLogBuilder;
@@ -178,24 +185,24 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
* Return {@code true} if desktop mode should be restricted to supported devices.
*/
@VisibleForTesting
- public boolean enforceDeviceRestrictions() {
+ static boolean enforceDeviceRestrictions() {
return ENFORCE_DEVICE_RESTRICTIONS;
}
/**
* Return {@code true} if the current device supports desktop mode.
*/
+ // TODO(b/337819319): use a companion object instead.
@VisibleForTesting
- public boolean isDesktopModeSupported(@NonNull Context context) {
+ static boolean isDesktopModeSupported(@NonNull Context context) {
return context.getResources().getBoolean(R.bool.config_isDesktopModeSupported);
}
/**
* Return {@code true} if desktop mode can be entered on the current device.
*/
- boolean canEnterDesktopMode(@NonNull Context context) {
+ static boolean canEnterDesktopMode(@NonNull Context context) {
return isDesktopModeEnabled()
&& (!enforceDeviceRestrictions() || isDesktopModeSupported(context));
}
-
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 9a7f87d04e88..9b98380dd5e8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3691,6 +3691,9 @@ class Task extends TaskFragment {
info.requestedVisibleTypes = topMainWin.getRequestedVisibleTypes();
}
}
+ final Rect rotatedBounds = activity.getFixedRotationTransformDisplayBounds();
+ info.taskBounds.set(rotatedBounds != null ? rotatedBounds
+ : info.taskInfo.configuration.windowConfiguration.getBounds());
// If the developer has persist a different configuration, we need to override it to the
// starting window because persisted configuration does not effect to Task.
info.taskInfo.configuration.setTo(activity.getConfiguration());
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index d91a2115a884..fd1b5bee7060 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -110,9 +110,9 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE;
private static final String TAG_CONFIGURATION = TAG + POSTFIX_CONFIGURATION;
- private static final int MAX_RAPID_ACTIVITY_LAUNCH_COUNT = 50;
+ private static final int MAX_RAPID_ACTIVITY_LAUNCH_COUNT = 200;
private static final long RAPID_ACTIVITY_LAUNCH_MS = 500;
- private static final long RESET_RAPID_ACTIVITY_LAUNCH_MS = 5 * RAPID_ACTIVITY_LAUNCH_MS;
+ private static final long RESET_RAPID_ACTIVITY_LAUNCH_MS = 3 * RAPID_ACTIVITY_LAUNCH_MS;
public static final int STOPPED_STATE_NOT_STOPPED = 0;
public static final int STOPPED_STATE_FIRST_LAUNCH = 1;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6458eace56cf..d555f1af1a10 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -666,15 +666,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
DELEGATION_CERT_SELECTION,
});
- /**
- * System property whose value indicates whether the device is fully owned by an organization:
- * it can be either a device owner device, or a device with an organization-owned managed
- * profile.
- *
- * <p>The state is stored as a Boolean string.
- */
- private static final String PROPERTY_ORGANIZATION_OWNED = "ro.organization_owned";
-
private static final int STATUS_BAR_DISABLE_MASK =
StatusBarManager.DISABLE_EXPAND |
StatusBarManager.DISABLE_NOTIFICATION_ICONS |
@@ -2356,7 +2347,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
void loadOwners() {
synchronized (getLockObject()) {
mOwners.load();
- setDeviceOwnershipSystemPropertyLocked();
if (mOwners.hasDeviceOwner()) {
setGlobalSettingDeviceOwnerType(
mOwners.getDeviceOwnerType(mOwners.getDeviceOwnerPackageName()));
@@ -2720,27 +2710,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
+ defaultRestrictions);
}
- private void setDeviceOwnershipSystemPropertyLocked() {
- final boolean deviceProvisioned =
- mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0;
- final boolean hasDeviceOwner = mOwners.hasDeviceOwner();
- final boolean hasOrgOwnedProfile = isOrganizationOwnedDeviceWithManagedProfile();
- // If the device is not provisioned and there is currently no management, do not set the
- // read-only system property yet, since device owner / org-owned profile may still be
- // provisioned.
- if (!hasDeviceOwner && !hasOrgOwnedProfile && !deviceProvisioned) {
- return;
- }
- final String value = Boolean.toString(hasDeviceOwner || hasOrgOwnedProfile);
- final String currentVal = mInjector.systemPropertiesGet(PROPERTY_ORGANIZATION_OWNED, null);
- if (TextUtils.isEmpty(currentVal)) {
- Slogf.i(LOG_TAG, "Set ro.organization_owned property to " + value);
- mInjector.systemPropertiesSet(PROPERTY_ORGANIZATION_OWNED, value);
- } else if (!value.equals(currentVal)) {
- Slogf.w(LOG_TAG, "Cannot change existing ro.organization_owned to " + value);
- }
- }
-
private void maybeStartSecurityLogMonitorOnActivityManagerReady() {
if (!mInjector.securityLogIsLoggingEnabled()) {
return;
@@ -9447,7 +9416,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mOwners.setDeviceOwner(admin, userId);
mOwners.writeDeviceOwner();
- setDeviceOwnershipSystemPropertyLocked();
//TODO(b/180371154): when provisionFullyManagedDevice is used in tests, remove this
// hard-coded default value setting.
@@ -15303,8 +15271,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private class SetupContentObserver extends ContentObserver {
private final Uri mUserSetupComplete = Settings.Secure.getUriFor(
Settings.Secure.USER_SETUP_COMPLETE);
- private final Uri mDeviceProvisioned = Settings.Global.getUriFor(
- Settings.Global.DEVICE_PROVISIONED);
private final Uri mPaired = Settings.Secure.getUriFor(Settings.Secure.DEVICE_PAIRED);
private final Uri mDefaultImeChanged = Settings.Secure.getUriFor(
Settings.Secure.DEFAULT_INPUT_METHOD);
@@ -15318,7 +15284,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
void register() {
mInjector.registerContentObserver(mUserSetupComplete, false, this, UserHandle.USER_ALL);
- mInjector.registerContentObserver(mDeviceProvisioned, false, this, UserHandle.USER_ALL);
if (mIsWatch) {
mInjector.registerContentObserver(mPaired, false, this, UserHandle.USER_ALL);
}
@@ -15334,12 +15299,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public void onChange(boolean selfChange, Uri uri, int userId) {
if (mUserSetupComplete.equals(uri) || (mIsWatch && mPaired.equals(uri))) {
updateUserSetupCompleteAndPaired();
- } else if (mDeviceProvisioned.equals(uri)) {
- synchronized (getLockObject()) {
- // Set PROPERTY_DEVICE_OWNER_PRESENT, for the SUW case where setting the property
- // is delayed until device is marked as provisioned.
- setDeviceOwnershipSystemPropertyLocked();
- }
} else if (mDefaultImeChanged.equals(uri)) {
synchronized (getLockObject()) {
if (mUserIdsWithPendingChangesByOwner.contains(userId)) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
index a0d9be549880..eeb49765cc9d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
@@ -16,6 +16,9 @@
package com.android.server.devicepolicy;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
+import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -185,6 +188,9 @@ final class PolicyEnforcerCallbacks {
}
}
+ // TODO: when a local policy exists for a user, this callback will be invoked for this user
+ // individually as well as for USER_ALL. This can be optimized by separating local and global
+ // enforcement in the policy engine.
static boolean setUserControlDisabledPackages(
@Nullable Set<String> packages, Context context, int userId, PolicyKey policyKey) {
Binder.withCleanCallingIdentity(() -> {
@@ -201,20 +207,35 @@ final class PolicyEnforcerCallbacks {
return;
}
final AppOpsManager appOpsManager = context.getSystemService(AppOpsManager.class);
- for (var pkg : packages) {
- final var appInfo = pmi.getApplicationInfo(pkg,
- PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
- Process.myUid(), userId);
- if (appInfo != null) {
- DevicePolicyManagerService.setBgUsageAppOp(appOpsManager, appInfo);
- }
- }
+ resolveUsers(userId).forEach(
+ user -> setBgUsageAppOp(packages, pmi, user, appOpsManager));
}
});
return true;
}
+ /** Handles USER_ALL expanding it into the list of all intact users. */
+ private static List<Integer> resolveUsers(int userId) {
+ if (userId == UserHandle.USER_ALL) {
+ UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
+ return userManager.getUsers(/* excludeDying= */ true)
+ .stream().map(ui -> ui.id).toList();
+ } else {
+ return List.of(userId);
+ }
+ }
+
+ private static void setBgUsageAppOp(Set<String> packages, PackageManagerInternal pmi,
+ int userId, AppOpsManager appOpsManager) {
+ for (var pkg : packages) {
+ int packageFlags = MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE;
+ final var appInfo = pmi.getApplicationInfo(pkg, packageFlags, Process.myUid(), userId);
+ if (appInfo != null) {
+ DevicePolicyManagerService.setBgUsageAppOp(appOpsManager, appInfo);
+ }
+ }
+ }
+
static boolean addPersistentPreferredActivity(
@Nullable ComponentName preferredActivity, @NonNull Context context, int userId,
@NonNull PolicyKey policyKey) {
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index c6f3eb357442..30e3b1808819 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -58,6 +58,7 @@ import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doNothing;
@@ -90,6 +91,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.PowerManagerInternal;
import android.os.RemoteException;
+import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.IStorageManager;
@@ -203,7 +205,10 @@ public class UserControllerTest {
doNothing().when(mInjector).activityManagerOnUserStopped(anyInt());
doNothing().when(mInjector).clearBroadcastQueueForUser(anyInt());
doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt());
- doNothing().when(mInjector).lockDeviceNowAndWaitForKeyguardShown();
+ doAnswer(invocation -> {
+ ((Runnable) invocation.getArgument(0)).run();
+ return null;
+ }).when(mInjector).showKeyguard(any());
mockIsUsersOnSecondaryDisplaysEnabled(false);
// All UserController params are set to default.
@@ -540,7 +545,6 @@ public class UserControllerTest {
expectedCodes.add(REPORT_USER_SWITCH_COMPLETE_MSG);
if (backgroundUserStopping) {
expectedCodes.add(CLEAR_USER_JOURNEY_SESSION_MSG);
- expectedCodes.add(0); // this is for directly posting in stopping.
}
if (expectScheduleBackgroundUserStopping) {
expectedCodes.add(SCHEDULED_STOP_BACKGROUND_USER_MSG);
@@ -1419,21 +1423,13 @@ public class UserControllerTest {
// mock the device to be secure in order to expect the keyguard to be shown
when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
- // call real lockDeviceNowAndWaitForKeyguardShown method for this test
- doCallRealMethod().when(mInjector).lockDeviceNowAndWaitForKeyguardShown();
+ // call real showKeyguard method for this test
+ doCallRealMethod().when(mInjector).showKeyguard(any());
- // call startUser on a thread because we're expecting it to be blocked
- Thread threadStartUser = new Thread(()-> {
- mUserController.startUser(TEST_USER_ID, USER_START_MODE_FOREGROUND);
- });
- threadStartUser.start();
+ mUserController.completeUserSwitch(TEST_USER_ID1, TEST_USER_ID2);
- // make sure the switch is stalled...
- Thread.sleep(2000);
- // by checking REPORT_USER_SWITCH_MSG is not sent yet
- assertNull(mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG));
- // and the thread is still alive
- assertTrue(threadStartUser.isAlive());
+ // make sure the switch is stalled by checking the UserSwitchingDialog is not dismissed yet
+ verify(mInjector, never()).dismissUserSwitchingDialog(any());
// mock send the keyguard shown event
ArgumentCaptor<ActivityTaskManagerInternal.ScreenObserver> captor = ArgumentCaptor.forClass(
@@ -1441,12 +1437,42 @@ public class UserControllerTest {
verify(mInjector.mActivityTaskManagerInternal).registerScreenObserver(captor.capture());
captor.getValue().onKeyguardStateChanged(true);
- // verify the switch now moves on...
- Thread.sleep(1000);
- // by checking REPORT_USER_SWITCH_MSG is sent
- assertNotNull(mInjector.mHandler.getMessageForCode(REPORT_USER_SWITCH_MSG));
- // and the thread is finished
- assertFalse(threadStartUser.isAlive());
+ // verify the switch now moves on by checking the UserSwitchingDialog is dismissed
+ verify(mInjector, atLeastOnce()).dismissUserSwitchingDialog(any());
+
+ // verify that SHOW_KEYGUARD_TIMEOUT is ignored and does not crash the system
+ try {
+ mInjector.mHandler.processPostDelayedCallbacksWithin(
+ UserController.SHOW_KEYGUARD_TIMEOUT_MS);
+ } catch (RuntimeException e) {
+ throw new AssertionError(
+ "SHOW_KEYGUARD_TIMEOUT is not ignored and crashed the system", e);
+ }
+ }
+
+ @Test
+ public void testRuntimeExceptionIsThrownIfTheKeyguardIsNotShown() throws Exception {
+ // enable user switch ui, because keyguard is only shown then
+ mUserController.setInitialConfig(/* userSwitchUiEnabled= */ true,
+ /* maxRunningUsers= */ 3, /* delayUserDataLocking= */ false,
+ /* backgroundUserScheduledStopTimeSecs= */ -1);
+
+ // mock the device to be secure in order to expect the keyguard to be shown
+ when(mInjector.mKeyguardManagerMock.isDeviceSecure(anyInt())).thenReturn(true);
+
+ // suppress showKeyguard method for this test
+ doNothing().when(mInjector).showKeyguard(any());
+
+ mUserController.completeUserSwitch(TEST_USER_ID1, TEST_USER_ID2);
+
+ // verify that the system has crashed
+ assertThrows("Should have thrown RuntimeException", RuntimeException.class, () -> {
+ mInjector.mHandler.processPostDelayedCallbacksWithin(
+ UserController.SHOW_KEYGUARD_TIMEOUT_MS);
+ });
+
+ // make sure the UserSwitchingDialog is not dismissed
+ verify(mInjector, never()).dismissUserSwitchingDialog(any());
}
private void setUpAndStartUserInBackground(int userId) throws Exception {
@@ -1793,7 +1819,9 @@ public class UserControllerTest {
Set<Integer> getMessageCodes() {
Set<Integer> result = new LinkedHashSet<>();
for (Message msg : mMessages) {
- result.add(msg.what);
+ if (msg.what != 0) { // ignore mHandle.post and mHandler.postDelayed messages
+ result.add(msg.what);
+ }
}
return result;
}
@@ -1817,14 +1845,28 @@ public class UserControllerTest {
@Override
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
+ final Runnable cb = msg.getCallback();
+ if (cb != null && uptimeMillis <= SystemClock.uptimeMillis()) {
+ // run mHandler.post calls immediately
+ cb.run();
+ return true;
+ }
Message copy = new Message();
copy.copyFrom(msg);
+ copy.setCallback(cb);
mMessages.add(copy);
- if (msg.getCallback() != null) {
- msg.getCallback().run();
- msg.setCallback(null);
- }
return super.sendMessageAtTime(msg, uptimeMillis);
}
+
+ public void processPostDelayedCallbacksWithin(long millis) {
+ final long whenMax = SystemClock.uptimeMillis() + millis;
+ for (Message msg : mMessages) {
+ final Runnable cb = msg.getCallback();
+ if (cb != null && msg.getWhen() <= whenMax) {
+ msg.setCallback(null);
+ cb.run();
+ }
+ }
+ }
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index ce7a0a03ea0a..74d8433700d3 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -243,7 +243,6 @@ import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.FlagsParameterization;
import android.platform.test.flag.junit.SetFlagsRule;
import android.platform.test.rule.LimitDevicesRule;
-import android.provider.DeviceConfig;
import android.provider.MediaStore;
import android.provider.Settings;
import android.service.notification.Adjustment;
@@ -280,7 +279,6 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import com.android.internal.R;
-import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.config.sysui.TestableFlagResolver;
import com.android.internal.logging.InstanceIdSequence;
import com.android.internal.logging.InstanceIdSequenceFake;
@@ -602,7 +600,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mContext.getContentResolver()).thenReturn(cr);
doNothing().when(cr).registerContentObserver(any(), anyBoolean(), any(), anyInt());
- setDpmAppOppsExemptFromDismissal(false);
+ when(mAppOpsManager.checkOpNoThrow(
+ AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
+ mPkg)).thenReturn(AppOpsManager.MODE_IGNORED);
// Use this testable looper.
mTestableLooper = TestableLooper.get(this);
@@ -900,7 +900,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@After
public void tearDown() throws Exception {
if (mFile != null) mFile.delete();
- clearDeviceConfig();
if (mActivityIntent != null) {
mActivityIntent.cancel();
@@ -1200,19 +1199,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
return answers;
}
- private void clearDeviceConfig() {
- DeviceConfig.resetToDefaults(
- Settings.RESET_MODE_PACKAGE_DEFAULTS, DeviceConfig.NAMESPACE_SYSTEMUI);
- }
-
- private void setDefaultAssistantInDeviceConfig(String componentName) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_SYSTEMUI,
- SystemUiDeviceConfigFlags.NAS_DEFAULT_SERVICE,
- componentName,
- false);
- }
-
private Notification.Builder getMessageStyleNotifBuilder(boolean addBubbleMetadata,
String groupKey, boolean isSummary, boolean mutable) {
// Give it a person
@@ -9092,7 +9078,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void setDefaultAssistantForUser_fromConfigXml() {
- clearDeviceConfig();
ComponentName xmlConfig = new ComponentName("config", "xml");
ArraySet<ComponentName> components = new ArraySet<>(Arrays.asList(xmlConfig));
when(mResources
@@ -9115,51 +9100,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
- public void setDefaultAssistantForUser_fromDeviceConfig() {
- ComponentName xmlConfig = new ComponentName("xml", "config");
- ComponentName deviceConfig = new ComponentName("device", "config");
- setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
- when(mResources
- .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
- .thenReturn(xmlConfig.flattenToString());
- when(mContext.getResources()).thenReturn(mResources);
- when(mAssistants.queryPackageForServices(eq(null), anyInt(), anyInt()))
- .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
- when(mAssistants.getDefaultComponents())
- .thenReturn(new ArraySet<>(Arrays.asList(deviceConfig)));
- mService.setNotificationAssistantAccessGrantedCallback(
- mNotificationAssistantAccessGrantedCallback);
-
- mService.setDefaultAssistantForUser(0);
-
- verify(mNotificationAssistantAccessGrantedCallback)
- .onGranted(eq(deviceConfig), eq(0), eq(true), eq(false));
- }
-
- @Test
- public void setDefaultAssistantForUser_deviceConfigInvalid() {
- ComponentName xmlConfig = new ComponentName("xml", "config");
- ComponentName deviceConfig = new ComponentName("device", "config");
- setDefaultAssistantInDeviceConfig(deviceConfig.flattenToString());
- when(mResources
- .getString(com.android.internal.R.string.config_defaultAssistantAccessComponent))
- .thenReturn(xmlConfig.flattenToString());
- when(mContext.getResources()).thenReturn(mResources);
- // Only xmlConfig is valid, deviceConfig is not.
- when(mAssistants.queryPackageForServices(eq(null), anyInt(), eq(0)))
- .thenReturn(new ArraySet<>(Collections.singleton(xmlConfig)));
- when(mAssistants.getDefaultComponents())
- .thenReturn(new ArraySet<>(Arrays.asList(xmlConfig, deviceConfig)));
- mService.setNotificationAssistantAccessGrantedCallback(
- mNotificationAssistantAccessGrantedCallback);
-
- mService.setDefaultAssistantForUser(0);
-
- verify(mNotificationAssistantAccessGrantedCallback)
- .onGranted(eq(xmlConfig), eq(0), eq(true), eq(false));
- }
-
- @Test
public void clearMultipleDefaultAssistantPackagesShouldEnableOnlyOne() throws RemoteException {
ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
generateResetComponentValues();
@@ -11006,7 +10946,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
tr.addOverride(com.android.internal.R.string.config_defaultListenerAccessPackages, "");
tr.addOverride(com.android.internal.R.string.config_defaultDndAccessPackages, "");
tr.addOverride(com.android.internal.R.string.config_defaultAssistantAccessComponent, "");
- setDefaultAssistantInDeviceConfig("");
mService.loadDefaultApprovedServices(USER_SYSTEM);
@@ -13425,7 +13364,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
when(mDevicePolicyManager.isActiveDeviceOwner(mUid)).thenReturn(true);
// Given: a notification has the flag FLAG_ONGOING_EVENT set
- setDpmAppOppsExemptFromDismissal(false);
Notification n = new Notification.Builder(mContext, "test")
.setOngoing(true)
.build();
@@ -13451,7 +13389,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
mPkg)).thenReturn(AppOpsManager.MODE_ALLOWED);
// Given: a notification has the flag FLAG_ONGOING_EVENT set
- setDpmAppOppsExemptFromDismissal(true);
Notification n = new Notification.Builder(mContext, "test")
.setOngoing(true)
.build();
@@ -13459,8 +13396,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// When: fix the notification with NotificationManagerService
mService.fixNotification(n, mPkg, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE, true);
- // Then: the notification's flag FLAG_NO_DISMISS should be cleared
- assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
+ // Then: the notification's flag FLAG_NO_DISMISS should be set
+ assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
}
@Test
@@ -13468,9 +13405,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
when(mAppOpsManager.checkOpNoThrow(
AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
- mPkg)).thenReturn(AppOpsManager.MODE_ALLOWED);
+ mPkg)).thenReturn(AppOpsManager.MODE_IGNORED);
// Given: a notification has the flag FLAG_ONGOING_EVENT set
- setDpmAppOppsExemptFromDismissal(false);
Notification n = new Notification.Builder(mContext, "test")
.setOngoing(true)
.build();
@@ -15551,14 +15487,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
PendingIntent.FLAG_MUTABLE);
}
- private void setDpmAppOppsExemptFromDismissal(boolean isOn) {
- DeviceConfig.setProperty(
- DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
- /* name= */ "application_exemptions",
- String.valueOf(isOn),
- /* makeDefault= */ false);
- }
-
private void allowTestPackageToToast() throws Exception {
assertWithMessage("toast queue").that(mService.mToastQueue).isEmpty();
mService.isSystemUid = false;
diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
index 353ba01d3cf4..89ae802f474c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static com.android.server.wm.DesktopModeLaunchParamsModifier.DESKTOP_MODE_INITIAL_BOUNDS_SCALE;
+import static com.android.server.wm.DesktopModeLaunchParamsModifier.ENFORCE_DEVICE_RESTRICTIONS_KEY;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_BOUNDS;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.PHASE_DISPLAY;
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_CONTINUE;
@@ -29,18 +30,21 @@ import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.
import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
import static org.junit.Assert.assertEquals;
-import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+import android.content.res.Resources;
import android.graphics.Rect;
+import android.os.SystemProperties;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
+import com.android.internal.R;
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier.Result;
import com.android.window.flags.Flags;
@@ -48,6 +52,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
/**
* Tests for desktop mode task bounds.
@@ -71,8 +76,6 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
@Before
public void setUp() throws Exception {
mActivity = new ActivityBuilder(mAtm).build();
- mTarget = spy(new DesktopModeLaunchParamsModifier(mContext));
- doReturn(true).when(mTarget).isDesktopModeSupported(any());
mCurrent = new LaunchParamsController.LaunchParams();
mCurrent.reset();
mResult = new LaunchParamsController.LaunchParams();
@@ -82,20 +85,26 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
@Test
@DisableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsContinueIfDesktopWindowingIsDisabled() {
+ setupDesktopModeLaunchParamsModifier();
+
assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(null).calculate());
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsContinueIfDesktopWindowingIsEnabledOnUnsupportedDevice() {
- doReturn(false).when(mTarget).isDesktopModeSupported(any());
+ setupDesktopModeLaunchParamsModifier(/*isDesktopModeSupported=*/ false,
+ /*enforceDeviceRestrictions=*/ true);
+
assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(null).calculate());
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsDoneIfDesktopWindowingIsEnabledAndUnsupportedDeviceOverridden() {
- doReturn(false).when(mTarget).enforceDeviceRestrictions();
+ setupDesktopModeLaunchParamsModifier(/*isDesktopModeSupported=*/ true,
+ /*enforceDeviceRestrictions=*/ false);
+
final Task task = new TaskBuilder(mSupervisor).build();
assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
}
@@ -103,12 +112,16 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsSkipIfTaskIsNull() {
+ setupDesktopModeLaunchParamsModifier();
+
assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(null).calculate());
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsSkipIfNotBoundsPhase() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).build();
assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(task).setPhase(
PHASE_DISPLAY).calculate());
@@ -117,6 +130,8 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsSkipIfTaskNotUsingActivityTypeStandardOrUndefined() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_ASSISTANT).build();
assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(task).calculate());
@@ -125,6 +140,8 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsDoneIfTaskUsingActivityTypeStandard() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_STANDARD).build();
assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
@@ -133,6 +150,8 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsDoneIfTaskUsingActivityTypeUndefined() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_UNDEFINED).build();
assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
@@ -141,6 +160,8 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testReturnsSkipIfCurrentParamsHasBounds() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_STANDARD).build();
mCurrent.mBounds.set(/* left */ 0, /* top */ 0, /* right */ 100, /* bottom */ 100);
@@ -150,6 +171,8 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testUsesDefaultBounds() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_STANDARD).build();
final int displayHeight = 1600;
@@ -165,6 +188,8 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
@Test
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testUsesDisplayAreaAndWindowingModeFromSource() {
+ setupDesktopModeLaunchParamsModifier();
+
final Task task = new TaskBuilder(mSupervisor).setActivityType(
ACTIVITY_TYPE_STANDARD).build();
TaskDisplayArea mockTaskDisplayArea = mock(TaskDisplayArea.class);
@@ -176,6 +201,24 @@ public class DesktopModeLaunchParamsModifierTests extends WindowTestsBase {
assertEquals(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode);
}
+ private void setupDesktopModeLaunchParamsModifier() {
+ setupDesktopModeLaunchParamsModifier(/*isDesktopModeSupported=*/ true,
+ /*enforceDeviceRestrictions=*/ true);
+ }
+
+ private void setupDesktopModeLaunchParamsModifier(boolean isDesktopModeSupported,
+ boolean enforceDeviceRestrictions) {
+ Resources mockResources = Mockito.mock(Resources.class);
+ when(mockResources.getBoolean(eq(R.bool.config_isDesktopModeSupported)))
+ .thenReturn(isDesktopModeSupported);
+ doReturn(mockResources).when(mContext).getResources();
+
+ SystemProperties.set(ENFORCE_DEVICE_RESTRICTIONS_KEY,
+ String.valueOf(enforceDeviceRestrictions));
+
+ mTarget = new DesktopModeLaunchParamsModifier(mContext);
+ }
+
private class CalculateRequestBuilder {
private Task mTask;
private int mPhase = PHASE_BOUNDS;
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index ac1dc087fedb..8677738f3edc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -4193,11 +4193,49 @@ public class SizeCompatTests extends WindowTestsBase {
}
@Test
+ @EnableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION})
+ public void testPortraitCloseToSquareDisplayWithTaskbar_insetsOverridden_notLetterboxed() {
+ // Set up portrait close to square display.
+ setUpDisplaySizeWithApp(2200, 2280);
+ final DisplayContent display = mActivity.mDisplayContent;
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ // Simulate insets, final app bounds are (0, 0, 2200, 2130) - landscape.
+ final WindowState navbar = createWindow(null, TYPE_NAVIGATION_BAR, mDisplayContent,
+ "navbar");
+ final Binder owner = new Binder();
+ navbar.mAttrs.providedInsets = new InsetsFrameProvider[] {
+ new InsetsFrameProvider(owner, 0, WindowInsets.Type.navigationBars())
+ .setInsetsSize(Insets.of(0, 0, 0, 150))
+ };
+ display.getDisplayPolicy().addWindowLw(navbar, navbar.mAttrs);
+ assertTrue(display.getDisplayPolicy().updateDecorInsetsInfo());
+ display.sendNewConfiguration();
+
+ final ActivityRecord activity = new ActivityBuilder(mAtm)
+ .setTask(mTask)
+ .setScreenOrientation(SCREEN_ORIENTATION_PORTRAIT)
+ .setComponent(ComponentName.createRelative(mContext,
+ SizeCompatTests.class.getName()))
+ .setUid(android.os.Process.myUid())
+ .build();
+
+ // Activity should not be letterboxed and should have portrait app bounds even though
+ // orientation is not respected with insets as insets have been decoupled.
+ final Rect appBounds = activity.getWindowConfiguration().getAppBounds();
+ final Rect displayBounds = display.getBounds();
+ assertFalse(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertNotNull(appBounds);
+ assertEquals(displayBounds.width(), appBounds.width());
+ assertEquals(displayBounds.height(), appBounds.height());
+ }
+
+ @Test
@DisableCompatChanges({ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED})
public void testPortraitCloseToSquareDisplayWithTaskbar_letterboxed() {
// Set up portrait close to square display
setUpDisplaySizeWithApp(2200, 2280);
final DisplayContent display = mActivity.mDisplayContent;
+ display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
// Simulate taskbar, final app bounds are (0, 0, 2200, 2130) - landscape
final WindowState navbar = createWindow(null, TYPE_NAVIGATION_BAR, mDisplayContent,
"navbar");
diff --git a/tests/FlickerTests/IME/AndroidTestTemplate.xml b/tests/FlickerTests/IME/AndroidTestTemplate.xml
index 988f76f4175c..38442db699f8 100644
--- a/tests/FlickerTests/IME/AndroidTestTemplate.xml
+++ b/tests/FlickerTests/IME/AndroidTestTemplate.xml
@@ -10,6 +10,8 @@
<target_preparer class="com.android.tradefed.targetprep.DeviceSetup">
<!-- keeps the screen on during tests -->
<option name="screen-always-on" value="on"/>
+ <!-- enable AOD -->
+ <option name="set-secure-setting" key="doze_always_on" value="1" />
<!-- prevents the phone from restarting -->
<option name="force-skip-system-props" value="true"/>
<!-- set WM tracing verbose level to all -->
diff --git a/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt
new file mode 100644
index 000000000000..31506b5eabf0
--- /dev/null
+++ b/tests/FlickerTests/IME/src/com/android/server/wm/flicker/ime/ShowImeOnUnlockScreenTest.kt
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm.flicker.ime
+
+import android.platform.test.annotations.Presubmit
+import android.platform.test.rule.UnlockScreenRule
+import android.tools.Rotation
+import android.tools.flicker.junit.FlickerParametersRunnerFactory
+import android.tools.flicker.legacy.FlickerBuilder
+import android.tools.flicker.legacy.LegacyFlickerTest
+import android.tools.flicker.legacy.LegacyFlickerTestFactory
+import android.tools.traces.component.ComponentNameMatcher
+import com.android.server.wm.flicker.BaseTest
+import com.android.server.wm.flicker.helpers.ImeAppHelper
+import org.junit.FixMethodOrder
+import org.junit.Ignore
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.MethodSorters
+import org.junit.runners.Parameterized
+
+/**
+ * Test IME window closing on lock and opening on screen unlock. To run this test: `atest
+ * FlickerTests:CloseImeWindowToHomeTest`
+ */
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class ShowImeOnUnlockScreenTest(flicker: LegacyFlickerTest) : BaseTest(flicker) {
+ private val testApp = ImeAppHelper(instrumentation)
+ private val imeOrSnapshot = ComponentNameMatcher.IME.or(ComponentNameMatcher.IME_SNAPSHOT)
+
+ /** {@inheritDoc} */
+ override val transition: FlickerBuilder.() -> Unit = {
+ setup {
+ tapl.expectedRotationCheckEnabled = false
+ testApp.launchViaIntent(wmHelper)
+ testApp.openIME(wmHelper)
+ }
+ transitions {
+ device.sleep()
+ wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
+ UnlockScreenRule.unlockScreen(device)
+ wmHelper.StateSyncBuilder().withImeShown().waitForAndVerify()
+ }
+ teardown { testApp.exit(wmHelper) }
+ }
+
+ @Presubmit
+ @Test
+ fun imeAndAppAnimateTogetherWhenLockingAndUnlocking() {
+ flicker.assertLayers {
+ this.isVisible(testApp)
+ .isVisible(imeOrSnapshot)
+ .then()
+ .isInvisible(testApp)
+ .isInvisible(imeOrSnapshot)
+ .then()
+ .isVisible(testApp)
+ .isVisible(imeOrSnapshot)
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Test
+ @Ignore("Not applicable to this CUJ. Display turns off during transition")
+ override fun navBarWindowIsAlwaysVisible() {}
+
+ /** {@inheritDoc} */
+ @Test
+ @Ignore("Not applicable to this CUJ. Display turns off during transition")
+ override fun statusBarWindowIsAlwaysVisible() {}
+
+ /** {@inheritDoc} */
+ @Test
+ @Ignore("Not applicable to this CUJ. Display turns off during transition")
+ override fun taskBarWindowIsAlwaysVisible() {}
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams() =
+ LegacyFlickerTestFactory.nonRotationTests(
+ supportedRotations = listOf(Rotation.ROTATION_0)
+ )
+ }
+}