summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java7
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java121
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java7
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobStore.java3
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/Agent.java6
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java18
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/Analyst.java141
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java90
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java18
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java6
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java183
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java26
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/README.md21
-rw-r--r--apex/jobscheduler/service/java/com/android/server/tare/Scribe.java28
-rw-r--r--apex/jobscheduler/service/jni/com_android_server_alarm_AlarmManagerService.cpp80
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.cpp37
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.h11
-rw-r--r--cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl6
-rw-r--r--core/api/current.txt34
-rw-r--r--core/java/android/app/Activity.java5
-rw-r--r--core/java/android/app/ActivityClient.java6
-rw-r--r--core/java/android/app/ActivityManagerInternal.java3
-rw-r--r--core/java/android/app/IActivityClientController.aidl4
-rw-r--r--core/java/android/companion/CompanionDeviceManager.java34
-rw-r--r--core/java/android/companion/ICompanionDeviceManager.aidl2
-rw-r--r--core/java/android/companion/OWNERS4
-rw-r--r--core/java/android/content/Context.java14
-rw-r--r--core/java/android/content/pm/PermissionMethod.java2
-rw-r--r--core/java/android/content/pm/PermissionName.java35
-rw-r--r--core/java/android/os/Trace.java9
-rw-r--r--core/java/android/provider/DeviceConfig.java7
-rw-r--r--core/java/android/security/keymaster/KeymasterDefs.java1
-rw-r--r--core/java/android/text/GraphemeClusterSegmentFinder.java (renamed from core/java/android/text/GraphemeClusterSegmentIterator.java)12
-rw-r--r--core/java/android/text/Layout.java413
-rw-r--r--core/java/android/text/SegmentFinder.java (renamed from core/java/android/text/SegmentIterator.java)66
-rw-r--r--core/java/android/text/WordSegmentFinder.java (renamed from core/java/android/text/WordSegmentIterator.java)25
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java38
-rw-r--r--core/java/android/widget/TextView.java15
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl5
-rw-r--r--core/java/com/android/internal/view/IInputMethodManager.aidl1
-rw-r--r--core/jni/android_media_AudioVolumeGroups.cpp5
-rw-r--r--core/jni/android_os_Trace.cpp27
-rw-r--r--core/tests/coretests/src/android/os/TraceTest.java16
-rw-r--r--core/tests/coretests/src/android/text/LayoutGetRangeForRectTest.java408
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java42
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java11
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl7
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java17
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java27
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt59
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt254
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/MultiWindowUtils.kt16
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NotificationListener.kt24
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt1
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt44
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt22
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt16
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt61
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt28
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenShellTransit.kt5
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt17
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt41
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt64
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt3
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt44
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt42
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt6
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt27
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt19
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt43
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt44
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt19
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt3
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt84
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt10
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt13
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt13
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipTestBase.kt5
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt26
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt160
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt82
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt3
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt50
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt96
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt23
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt20
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt167
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt78
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt78
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt82
-rw-r--r--media/java/android/media/MediaRoute2Info.java54
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java22
-rw-r--r--packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java2
-rw-r--r--packages/SystemUI/res/values/strings.xml31
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl5
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/SimpleMirrorWindowControl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java62
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java111
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java45
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt34
-rw-r--r--services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java59
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java12
-rw-r--r--services/core/java/com/android/server/AlarmManagerInternal.java13
-rw-r--r--services/core/java/com/android/server/SystemClockTime.java174
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java16
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java20
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthResult.java40
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthResultCoordinator.java93
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java157
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthSessionListener.java49
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/MultiBiometricLockoutState.java117
-rw-r--r--services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java4
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java47
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodUtils.java45
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java62
-rw-r--r--services/core/java/com/android/server/media/MediaRouterService.java82
-rw-r--r--services/core/java/com/android/server/om/IdmapDaemon.java9
-rw-r--r--services/core/java/com/android/server/timedetector/ConfigurationInternal.java58
-rw-r--r--services/core/java/com/android/server/timedetector/EnvironmentImpl.java40
-rw-r--r--services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java15
-rw-r--r--services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java215
-rw-r--r--services/core/java/com/android/server/wm/ActivityClientController.java6
-rw-r--r--services/core/java/com/android/server/wm/Task.java51
-rw-r--r--services/core/jni/Android.bp1
-rw-r--r--services/core/jni/OWNERS1
-rw-r--r--services/core/jni/com_android_server_SystemClockTime.cpp126
-rw-r--r--services/core/jni/onload.cpp2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java22
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/tare/CompleteEconomicPolicyTest.java68
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthResultCoordinatorTest.java94
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthSessionCoordinatorTest.java100
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/MultiBiometricLockoutStateTest.java148
-rw-r--r--services/tests/servicestests/src/com/android/server/tare/AnalystTest.java54
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java313
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java10
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java36
-rwxr-xr-xtelephony/java/com/android/internal/telephony/ISub.aidl8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt59
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt191
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplit.kt50
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt26
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt29
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt32
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt24
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt22
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt9
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt3
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt37
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt62
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt32
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt11
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt11
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt16
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt20
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt21
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt21
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt118
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt4
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt7
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt47
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt45
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt61
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt38
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt49
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt13
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt53
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt65
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowAndCloseTest.kt27
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt38
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt40
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt99
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt58
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt56
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt22
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt30
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt26
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest_ShellTransit.kt8
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt61
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt32
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt39
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt42
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt80
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt45
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt74
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt12
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt84
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt37
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt68
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt28
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt32
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt35
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt62
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt79
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt12
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt108
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt11
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt116
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt47
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt35
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt123
-rw-r--r--tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt2
-rw-r--r--tools/lint/checks/src/main/java/com/google/android/lint/Constants.kt4
-rw-r--r--tools/lint/checks/src/main/java/com/google/android/lint/PermissionMethodDetector.kt201
224 files changed, 5779 insertions, 4268 deletions
diff --git a/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
index 6af24be3a372..299ad66a882c 100644
--- a/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
+++ b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
@@ -91,6 +91,13 @@ public class EconomyManager {
}
}
+ public static final String KEY_ENABLE_TARE = "enable_tare";
+ public static final String KEY_ENABLE_POLICY_ALARM = "enable_policy_alarm";
+ public static final String KEY_ENABLE_POLICY_JOB_SCHEDULER = "enable_policy_job";
+ public static final boolean DEFAULT_ENABLE_TARE = true;
+ public static final boolean DEFAULT_ENABLE_POLICY_ALARM = true;
+ public static final boolean DEFAULT_ENABLE_POLICY_JOB_SCHEDULER = true;
+
// Keys for AlarmManager TARE factors
/** @hide */
public static final String KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED =
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index c622259ef7dc..232d3c9aaa53 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -39,6 +39,7 @@ import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROU
import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
import static android.os.UserHandle.USER_SYSTEM;
+import static com.android.server.SystemClockTime.TIME_CONFIDENCE_HIGH;
import static com.android.server.SystemTimeZone.TIME_ZONE_CONFIDENCE_HIGH;
import static com.android.server.SystemTimeZone.getTimeZoneId;
import static com.android.server.alarm.Alarm.APP_STANDBY_POLICY_INDEX;
@@ -58,9 +59,9 @@ import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_R
import static com.android.server.alarm.AlarmManagerService.RemovedAlarm.REMOVE_REASON_UNDEFINED;
import android.Manifest;
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.RequiresPermission;
import android.annotation.UserIdInt;
import android.app.Activity;
import android.app.ActivityManagerInternal;
@@ -89,7 +90,6 @@ import android.os.BatteryManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
-import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -103,7 +103,6 @@ import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.ThreadLocalWorkSource;
import android.os.Trace;
import android.os.UserHandle;
@@ -147,6 +146,8 @@ import com.android.server.DeviceIdleInternal;
import com.android.server.EventLogTags;
import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
+import com.android.server.SystemClockTime;
+import com.android.server.SystemClockTime.TimeConfidence;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
import com.android.server.SystemTimeZone;
@@ -883,9 +884,11 @@ public class AlarmManagerService extends SystemService {
mInjector.registerDeviceConfigListener(this);
final EconomyManagerInternal economyManagerInternal =
LocalServices.getService(EconomyManagerInternal.class);
- economyManagerInternal.registerTareStateChangeListener(this);
+ economyManagerInternal.registerTareStateChangeListener(this,
+ AlarmManagerEconomicPolicy.POLICY_ALARM);
onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_ALARM_MANAGER));
- updateTareSettings(economyManagerInternal.isEnabled());
+ updateTareSettings(
+ economyManagerInternal.isEnabled(AlarmManagerEconomicPolicy.POLICY_ALARM));
}
public void updateAllowWhileIdleWhitelistDurationLocked() {
@@ -1417,7 +1420,7 @@ public class AlarmManagerService extends SystemService {
private long convertToElapsed(long when, int type) {
if (isRtc(type)) {
- when -= mInjector.getCurrentTimeMillis() - mInjector.getElapsedRealtime();
+ when -= mInjector.getCurrentTimeMillis() - mInjector.getElapsedRealtimeMillis();
}
return when;
}
@@ -1577,7 +1580,7 @@ public class AlarmManagerService extends SystemService {
alarmsToDeliver = alarmsForUid;
mPendingBackgroundAlarms.remove(uid);
}
- deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
+ deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtimeMillis());
}
/**
@@ -1594,7 +1597,8 @@ public class AlarmManagerService extends SystemService {
mPendingBackgroundAlarms, alarmsToDeliver, this::isBackgroundRestricted);
if (alarmsToDeliver.size() > 0) {
- deliverPendingBackgroundAlarmsLocked(alarmsToDeliver, mInjector.getElapsedRealtime());
+ deliverPendingBackgroundAlarmsLocked(
+ alarmsToDeliver, mInjector.getElapsedRealtimeMillis());
}
}
@@ -1908,17 +1912,8 @@ public class AlarmManagerService extends SystemService {
mInjector.syncKernelTimeZoneOffset();
}
- // Ensure that we're booting with a halfway sensible current time. Use the
- // most recent of Build.TIME, the root file system's timestamp, and the
- // value of the ro.build.date.utc system property (which is in seconds).
- final long systemBuildTime = Long.max(
- 1000L * SystemProperties.getLong("ro.build.date.utc", -1L),
- Long.max(Environment.getRootDirectory().lastModified(), Build.TIME));
- if (mInjector.getCurrentTimeMillis() < systemBuildTime) {
- Slog.i(TAG, "Current time only " + mInjector.getCurrentTimeMillis()
- + ", advancing to build time " + systemBuildTime);
- mInjector.setKernelTime(systemBuildTime);
- }
+ // Ensure that we're booting with a halfway sensible current time.
+ mInjector.initializeTimeIfRequired();
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
// Determine SysUI's uid
@@ -2133,21 +2128,18 @@ public class AlarmManagerService extends SystemService {
}
}
- boolean setTimeImpl(long millis) {
- if (!mInjector.isAlarmDriverPresent()) {
- Slog.w(TAG, "Not setting time since no alarm driver is available.");
- return false;
- }
-
+ boolean setTimeImpl(
+ @CurrentTimeMillisLong long newSystemClockTimeMillis, @TimeConfidence int confidence,
+ @NonNull String logMsg) {
synchronized (mLock) {
- final long currentTimeMillis = mInjector.getCurrentTimeMillis();
- mInjector.setKernelTime(millis);
+ final long oldSystemClockTimeMillis = mInjector.getCurrentTimeMillis();
+ mInjector.setCurrentTimeMillis(newSystemClockTimeMillis, confidence, logMsg);
if (KERNEL_TIME_ZONE_SYNC_ENABLED) {
// Changing the time may cross a DST transition; sync the kernel offset if needed.
final TimeZone timeZone = TimeZone.getTimeZone(SystemTimeZone.getTimeZoneId());
- final int currentTzOffset = timeZone.getOffset(currentTimeMillis);
- final int newTzOffset = timeZone.getOffset(millis);
+ final int currentTzOffset = timeZone.getOffset(oldSystemClockTimeMillis);
+ final int newTzOffset = timeZone.getOffset(newSystemClockTimeMillis);
if (currentTzOffset != newTzOffset) {
Slog.i(TAG, "Timezone offset has changed, updating kernel timezone");
mInjector.setKernelTimeZoneOffset(newTzOffset);
@@ -2260,7 +2252,7 @@ public class AlarmManagerService extends SystemService {
triggerAtTime = 0;
}
- final long nowElapsed = mInjector.getElapsedRealtime();
+ final long nowElapsed = mInjector.getElapsedRealtimeMillis();
final long nominalTrigger = convertToElapsed(triggerAtTime, type);
// Try to prevent spamming by making sure apps aren't firing alarms in the immediate future
final long minTrigger = nowElapsed
@@ -2383,7 +2375,7 @@ public class AlarmManagerService extends SystemService {
// No need to fuzz as this is already earlier than the coming wake-from-idle.
return changedBeforeFuzz;
}
- final long nowElapsed = mInjector.getElapsedRealtime();
+ final long nowElapsed = mInjector.getElapsedRealtimeMillis();
final long futurity = upcomingWakeFromIdle - nowElapsed;
if (futurity <= mConstants.MIN_DEVICE_IDLE_FUZZ) {
@@ -2405,7 +2397,7 @@ public class AlarmManagerService extends SystemService {
* @return {@code true} if the alarm delivery time was updated.
*/
private boolean adjustDeliveryTimeBasedOnBatterySaver(Alarm alarm) {
- final long nowElapsed = mInjector.getElapsedRealtime();
+ final long nowElapsed = mInjector.getElapsedRealtimeMillis();
if (isExemptFromBatterySaver(alarm)) {
return false;
}
@@ -2472,7 +2464,7 @@ public class AlarmManagerService extends SystemService {
* @return {@code true} if the alarm delivery time was updated.
*/
private boolean adjustDeliveryTimeBasedOnDeviceIdle(Alarm alarm) {
- final long nowElapsed = mInjector.getElapsedRealtime();
+ final long nowElapsed = mInjector.getElapsedRealtimeMillis();
if (mPendingIdleUntil == null || mPendingIdleUntil == alarm) {
return alarm.setPolicyElapsed(DEVICE_IDLE_POLICY_INDEX, nowElapsed);
}
@@ -2527,7 +2519,7 @@ public class AlarmManagerService extends SystemService {
* adjustments made in this call.
*/
private boolean adjustDeliveryTimeBasedOnBucketLocked(Alarm alarm) {
- final long nowElapsed = mInjector.getElapsedRealtime();
+ final long nowElapsed = mInjector.getElapsedRealtimeMillis();
if (mConstants.USE_TARE_POLICY || isExemptFromAppStandby(alarm) || mAppStandbyParole) {
return alarm.setPolicyElapsed(APP_STANDBY_POLICY_INDEX, nowElapsed);
}
@@ -2587,7 +2579,7 @@ public class AlarmManagerService extends SystemService {
* adjustments made in this call.
*/
private boolean adjustDeliveryTimeBasedOnTareLocked(Alarm alarm) {
- final long nowElapsed = mInjector.getElapsedRealtime();
+ final long nowElapsed = mInjector.getElapsedRealtimeMillis();
if (!mConstants.USE_TARE_POLICY
|| isExemptFromTare(alarm) || hasEnoughWealthLocked(alarm)) {
return alarm.setPolicyElapsed(TARE_POLICY_INDEX, nowElapsed);
@@ -2643,7 +2635,7 @@ public class AlarmManagerService extends SystemService {
ent.pkg = a.sourcePackage;
ent.tag = a.statsTag;
ent.op = "START IDLE";
- ent.elapsedRealtime = mInjector.getElapsedRealtime();
+ ent.elapsedRealtime = mInjector.getElapsedRealtimeMillis();
ent.argRealtime = a.getWhenElapsed();
mAllowWhileIdleDispatches.add(ent);
}
@@ -2719,6 +2711,13 @@ public class AlarmManagerService extends SystemService {
}
@Override
+ public void setTime(
+ @CurrentTimeMillisLong long unixEpochTimeMillis, int confidence,
+ String logMsg) {
+ setTimeImpl(unixEpochTimeMillis, confidence, logMsg);
+ }
+
+ @Override
public void registerInFlightListener(InFlightListener callback) {
synchronized (mLock) {
mInFlightListeners.add(callback);
@@ -2987,12 +2986,16 @@ public class AlarmManagerService extends SystemService {
}
@Override
- public boolean setTime(long millis) {
+ public boolean setTime(@CurrentTimeMillisLong long millis) {
getContext().enforceCallingOrSelfPermission(
"android.permission.SET_TIME",
"setTime");
- return setTimeImpl(millis);
+ // The public API (and the shell command that also uses this method) have no concept
+ // of confidence, but since the time should come either from apps working on behalf of
+ // the user or a developer, confidence is assumed "high".
+ final int timeConfidence = TIME_CONFIDENCE_HIGH;
+ return setTimeImpl(millis, timeConfidence, "AlarmManager.setTime() called");
}
@Override
@@ -3142,7 +3145,7 @@ public class AlarmManagerService extends SystemService {
pw.println();
}
- final long nowELAPSED = mInjector.getElapsedRealtime();
+ final long nowELAPSED = mInjector.getElapsedRealtimeMillis();
final long nowUPTIME = SystemClock.uptimeMillis();
final long nowRTC = mInjector.getCurrentTimeMillis();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
@@ -3618,7 +3621,7 @@ public class AlarmManagerService extends SystemService {
synchronized (mLock) {
final long nowRTC = mInjector.getCurrentTimeMillis();
- final long nowElapsed = mInjector.getElapsedRealtime();
+ final long nowElapsed = mInjector.getElapsedRealtimeMillis();
proto.write(AlarmManagerServiceDumpProto.CURRENT_TIME, nowRTC);
proto.write(AlarmManagerServiceDumpProto.ELAPSED_REALTIME, nowElapsed);
proto.write(AlarmManagerServiceDumpProto.LAST_TIME_CHANGE_CLOCK_TIME,
@@ -3956,7 +3959,7 @@ public class AlarmManagerService extends SystemService {
void rescheduleKernelAlarmsLocked() {
// Schedule the next upcoming wakeup alarm. If there is a deliverable batch
// prior to that which contains no wakeups, we schedule that as well.
- final long nowElapsed = mInjector.getElapsedRealtime();
+ final long nowElapsed = mInjector.getElapsedRealtimeMillis();
long nextNonWakeup = 0;
if (mAlarmStore.size() > 0) {
final long firstWakeup = mAlarmStore.getNextWakeupDeliveryTime();
@@ -4069,7 +4072,7 @@ public class AlarmManagerService extends SystemService {
@GuardedBy("mLock")
private void removeAlarmsInternalLocked(Predicate<Alarm> whichAlarms, int reason) {
final long nowRtc = mInjector.getCurrentTimeMillis();
- final long nowElapsed = mInjector.getElapsedRealtime();
+ final long nowElapsed = mInjector.getElapsedRealtimeMillis();
final ArrayList<Alarm> removedAlarms = mAlarmStore.remove(whichAlarms);
final boolean removedFromStore = !removedAlarms.isEmpty();
@@ -4208,7 +4211,7 @@ public class AlarmManagerService extends SystemService {
void interactiveStateChangedLocked(boolean interactive) {
if (mInteractive != interactive) {
mInteractive = interactive;
- final long nowELAPSED = mInjector.getElapsedRealtime();
+ final long nowELAPSED = mInjector.getElapsedRealtimeMillis();
if (interactive) {
if (mPendingNonWakeupAlarms.size() > 0) {
final long thisDelayTime = nowELAPSED - mStartCurrentDelayTime;
@@ -4310,7 +4313,6 @@ public class AlarmManagerService extends SystemService {
private static native void close(long nativeData);
private static native int set(long nativeData, int type, long seconds, long nanoseconds);
private static native int waitForAlarm(long nativeData);
- private static native int setKernelTime(long nativeData, long millis);
/*
* b/246256335: The @Keep ensures that the native definition is kept even when the optimizer can
@@ -4357,7 +4359,7 @@ public class AlarmManagerService extends SystemService {
ent.pkg = alarm.sourcePackage;
ent.tag = alarm.statsTag;
ent.op = "END IDLE";
- ent.elapsedRealtime = mInjector.getElapsedRealtime();
+ ent.elapsedRealtime = mInjector.getElapsedRealtimeMillis();
ent.argRealtime = alarm.getWhenElapsed();
mAllowWhileIdleDispatches.add(ent);
}
@@ -4602,20 +4604,27 @@ public class AlarmManagerService extends SystemService {
setKernelTimeZoneOffset(utcOffsetMillis);
}
- void setKernelTime(long millis) {
- if (mNativeData != 0) {
- AlarmManagerService.setKernelTime(mNativeData, millis);
- }
+ void initializeTimeIfRequired() {
+ SystemClockTime.initializeIfRequired();
+ }
+
+ void setCurrentTimeMillis(
+ @CurrentTimeMillisLong long unixEpochMillis,
+ @TimeConfidence int confidence,
+ @NonNull String logMsg) {
+ SystemClockTime.setTimeAndConfidence(unixEpochMillis, confidence, logMsg);
}
void close() {
AlarmManagerService.close(mNativeData);
}
- long getElapsedRealtime() {
+ @ElapsedRealtimeLong
+ long getElapsedRealtimeMillis() {
return SystemClock.elapsedRealtime();
}
+ @CurrentTimeMillisLong
long getCurrentTimeMillis() {
return System.currentTimeMillis();
}
@@ -4665,7 +4674,7 @@ public class AlarmManagerService extends SystemService {
while (true) {
int result = mInjector.waitForAlarm();
final long nowRTC = mInjector.getCurrentTimeMillis();
- final long nowELAPSED = mInjector.getElapsedRealtime();
+ final long nowELAPSED = mInjector.getElapsedRealtimeMillis();
synchronized (mLock) {
mLastWakeup = nowELAPSED;
}
@@ -4913,7 +4922,7 @@ public class AlarmManagerService extends SystemService {
// this way, so WAKE_UP alarms will be delivered only when the device is awake.
ArrayList<Alarm> triggerList = new ArrayList<Alarm>();
synchronized (mLock) {
- final long nowELAPSED = mInjector.getElapsedRealtime();
+ final long nowELAPSED = mInjector.getElapsedRealtimeMillis();
triggerAlarmsLocked(triggerList, nowELAPSED);
updateNextAlarmClockLocked();
}
@@ -5090,7 +5099,7 @@ public class AlarmManagerService extends SystemService {
flags |= mConstants.TIME_TICK_ALLOWED_WHILE_IDLE ? FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
: 0;
- setImpl(ELAPSED_REALTIME, mInjector.getElapsedRealtime() + tickEventDelay, 0,
+ setImpl(ELAPSED_REALTIME, mInjector.getElapsedRealtimeMillis() + tickEventDelay, 0,
0, null, mTimeTickTrigger, TIME_TICK_TAG, flags, workSource, null,
Process.myUid(), "android", null, EXACT_ALLOW_REASON_ALLOW_LIST);
@@ -5277,7 +5286,7 @@ public class AlarmManagerService extends SystemService {
}
synchronized (mLock) {
mTemporaryQuotaReserve.replenishQuota(packageName, userId, quotaBump,
- mInjector.getElapsedRealtime());
+ mInjector.getElapsedRealtimeMillis());
}
mHandler.obtainMessage(AlarmHandler.TEMPORARY_QUOTA_CHANGED, userId, -1,
packageName).sendToTarget();
@@ -5439,7 +5448,7 @@ public class AlarmManagerService extends SystemService {
}
private void updateStatsLocked(InFlight inflight) {
- final long nowELAPSED = mInjector.getElapsedRealtime();
+ final long nowELAPSED = mInjector.getElapsedRealtimeMillis();
BroadcastStats bs = inflight.mBroadcastStats;
bs.nesting--;
if (bs.nesting <= 0) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 1775d908e21b..f5c0ed9f03f7 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -116,6 +116,7 @@ import com.android.server.job.restrictions.JobRestriction;
import com.android.server.job.restrictions.ThermalStatusRestriction;
import com.android.server.pm.UserManagerInternal;
import com.android.server.tare.EconomyManagerInternal;
+import com.android.server.tare.JobSchedulerEconomicPolicy;
import com.android.server.usage.AppStandbyInternal;
import com.android.server.usage.AppStandbyInternal.AppIdleStateChangeListener;
import com.android.server.utils.quota.Categorizer;
@@ -373,10 +374,12 @@ public class JobSchedulerService extends com.android.server.SystemService
JobSchedulerBackgroundThread.getExecutor(), this);
final EconomyManagerInternal economyManagerInternal =
LocalServices.getService(EconomyManagerInternal.class);
- economyManagerInternal.registerTareStateChangeListener(this);
+ economyManagerInternal
+ .registerTareStateChangeListener(this, JobSchedulerEconomicPolicy.POLICY_JOB);
// Load all the constants.
synchronized (mLock) {
- mConstants.updateTareSettingsLocked(economyManagerInternal.isEnabled());
+ mConstants.updateTareSettingsLocked(
+ economyManagerInternal.isEnabled(JobSchedulerEconomicPolicy.POLICY_JOB));
}
onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_JOB_SCHEDULER));
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
index 78ab06c9e332..ff4d26dc807d 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobStore.java
@@ -1095,6 +1095,8 @@ public final class JobStore {
}
if ((netCapabilitiesIntArray != null) && (netTransportTypesIntArray != null)) {
+ // S+ format. No capability or transport validation since the values should be in
+ // line with what's defined in the Connectivity mainline module.
final NetworkRequest.Builder builder = new NetworkRequest.Builder()
.clearCapabilities();
@@ -1111,6 +1113,7 @@ public final class JobStore {
}
jobBuilder.setRequiredNetwork(builder.build());
} else if (netCapabilitiesLong != null && netTransportTypesLong != null) {
+ // Format used on R- builds. Drop any unexpected capabilities and transports.
final NetworkRequest.Builder builder = new NetworkRequest.Builder()
.clearCapabilities();
final int maxNetCapabilityInR = NET_CAPABILITY_TEMPORARILY_NOT_METERED;
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
index 12ec9a4624e7..7a13e3f1fad7 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Agent.java
@@ -1196,7 +1196,11 @@ class Agent {
final EconomyManagerInternal.AnticipatedAction aa = anticipatedActions.get(i);
final EconomicPolicy.Action action = economicPolicy.getAction(aa.actionId);
if (action == null) {
- throw new IllegalArgumentException("Invalid action id: " + aa.actionId);
+ if ((aa.actionId & EconomicPolicy.ALL_POLICIES) == 0) {
+ throw new IllegalArgumentException("Invalid action id: " + aa.actionId);
+ } else {
+ Slog.w(TAG, "Tracking disabled policy's action? " + aa.actionId);
+ }
}
}
mListener = listener;
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java
index e791e98a6698..b426f16744e3 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java
@@ -117,23 +117,23 @@ public class AlarmManagerEconomicPolicy extends EconomicPolicy {
private static final String TAG = "TARE- " + AlarmManagerEconomicPolicy.class.getSimpleName();
public static final int ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE =
- TYPE_ACTION | POLICY_AM | 0;
+ TYPE_ACTION | POLICY_ALARM | 0;
public static final int ACTION_ALARM_WAKEUP_EXACT =
- TYPE_ACTION | POLICY_AM | 1;
+ TYPE_ACTION | POLICY_ALARM | 1;
public static final int ACTION_ALARM_WAKEUP_INEXACT_ALLOW_WHILE_IDLE =
- TYPE_ACTION | POLICY_AM | 2;
+ TYPE_ACTION | POLICY_ALARM | 2;
public static final int ACTION_ALARM_WAKEUP_INEXACT =
- TYPE_ACTION | POLICY_AM | 3;
+ TYPE_ACTION | POLICY_ALARM | 3;
public static final int ACTION_ALARM_NONWAKEUP_EXACT_ALLOW_WHILE_IDLE =
- TYPE_ACTION | POLICY_AM | 4;
+ TYPE_ACTION | POLICY_ALARM | 4;
public static final int ACTION_ALARM_NONWAKEUP_EXACT =
- TYPE_ACTION | POLICY_AM | 5;
+ TYPE_ACTION | POLICY_ALARM | 5;
public static final int ACTION_ALARM_NONWAKEUP_INEXACT_ALLOW_WHILE_IDLE =
- TYPE_ACTION | POLICY_AM | 6;
+ TYPE_ACTION | POLICY_ALARM | 6;
public static final int ACTION_ALARM_NONWAKEUP_INEXACT =
- TYPE_ACTION | POLICY_AM | 7;
+ TYPE_ACTION | POLICY_ALARM | 7;
public static final int ACTION_ALARM_CLOCK =
- TYPE_ACTION | POLICY_AM | 8;
+ TYPE_ACTION | POLICY_ALARM | 8;
private static final int[] COST_MODIFIERS = new int[]{
COST_MODIFIER_CHARGING,
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Analyst.java b/apex/jobscheduler/service/java/com/android/server/tare/Analyst.java
index bc6fe7e5a535..f27da4a1a4b2 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Analyst.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Analyst.java
@@ -16,6 +16,8 @@
package com.android.server.tare;
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+
import static com.android.server.tare.EconomicPolicy.TYPE_ACTION;
import static com.android.server.tare.EconomicPolicy.TYPE_REGULATION;
import static com.android.server.tare.EconomicPolicy.TYPE_REWARD;
@@ -23,9 +25,16 @@ import static com.android.server.tare.EconomicPolicy.getEventType;
import static com.android.server.tare.TareUtils.cakeToString;
import android.annotation.NonNull;
+import android.os.BatteryManagerInternal;
+import android.os.RemoteException;
import android.util.IndentingPrintWriter;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.IBatteryStats;
+import com.android.server.LocalServices;
+import com.android.server.am.BatteryStatsService;
+
import java.util.ArrayList;
import java.util.List;
@@ -38,6 +47,8 @@ public class Analyst {
|| Log.isLoggable(TAG, Log.DEBUG);
private static final int NUM_PERIODS_TO_RETAIN = 8;
+ @VisibleForTesting
+ static final long MIN_REPORT_DURATION_FOR_RESET = 24 * HOUR_IN_MILLIS;
static final class Report {
/** How much the battery was discharged over the tracked period. */
@@ -73,6 +84,22 @@ public class Analyst {
public long cumulativeNegativeRegulations = 0;
public int numNegativeRegulations = 0;
+ /**
+ * The approximate amount of time the screen has been off while on battery while this
+ * report has been active.
+ */
+ public long screenOffDurationMs = 0;
+ /**
+ * The approximate amount of battery discharge while this report has been active.
+ */
+ public long screenOffDischargeMah = 0;
+ /** The offset used to get the delta when polling the screen off time from BatteryStats. */
+ private long bsScreenOffRealtimeBase = 0;
+ /**
+ * The offset used to get the delta when polling the screen off discharge from BatteryStats.
+ */
+ private long bsScreenOffDischargeMahBase = 0;
+
private void clear() {
cumulativeBatteryDischarge = 0;
currentBatteryLevel = 0;
@@ -86,13 +113,27 @@ public class Analyst {
numPositiveRegulations = 0;
cumulativeNegativeRegulations = 0;
numNegativeRegulations = 0;
+ screenOffDurationMs = 0;
+ screenOffDischargeMah = 0;
+ bsScreenOffRealtimeBase = 0;
+ bsScreenOffDischargeMahBase = 0;
}
}
+ private final IBatteryStats mIBatteryStats;
+
private int mPeriodIndex = 0;
/** How much the battery was discharged over the tracked period. */
private final Report[] mReports = new Report[NUM_PERIODS_TO_RETAIN];
+ Analyst() {
+ this(BatteryStatsService.getService());
+ }
+
+ @VisibleForTesting Analyst(IBatteryStats iBatteryStats) {
+ mIBatteryStats = iBatteryStats;
+ }
+
/** Returns the list of most recent reports, with the oldest report first. */
@NonNull
List<Report> getReports() {
@@ -107,13 +148,35 @@ public class Analyst {
return list;
}
+ long getBatteryScreenOffDischargeMah() {
+ long discharge = 0;
+ for (Report report : mReports) {
+ if (report == null) {
+ continue;
+ }
+ discharge += report.screenOffDischargeMah;
+ }
+ return discharge;
+ }
+
+ long getBatteryScreenOffDurationMs() {
+ long duration = 0;
+ for (Report report : mReports) {
+ if (report == null) {
+ continue;
+ }
+ duration += report.screenOffDurationMs;
+ }
+ return duration;
+ }
+
/**
* Tracks the given reports instead of whatever is currently saved. Reports should be ordered
* oldest to most recent.
*/
void loadReports(@NonNull List<Report> reports) {
final int numReports = reports.size();
- mPeriodIndex = Math.max(0, numReports - 1);
+ mPeriodIndex = Math.max(0, Math.min(NUM_PERIODS_TO_RETAIN, numReports) - 1);
for (int i = 0; i < NUM_PERIODS_TO_RETAIN; ++i) {
if (i < numReports) {
mReports[i] = reports.get(i);
@@ -121,22 +184,38 @@ public class Analyst {
mReports[i] = null;
}
}
+ final Report latest = mReports[mPeriodIndex];
+ if (latest != null) {
+ latest.bsScreenOffRealtimeBase = getLatestBatteryScreenOffRealtimeMs();
+ latest.bsScreenOffDischargeMahBase = getLatestScreenOffDischargeMah();
+ }
}
void noteBatteryLevelChange(int newBatteryLevel) {
- if (newBatteryLevel == 100 && mReports[mPeriodIndex] != null
- && mReports[mPeriodIndex].currentBatteryLevel < newBatteryLevel) {
+ final boolean deviceDischargedEnough = mReports[mPeriodIndex] != null
+ && newBatteryLevel >= 90
+ // Battery level is increasing, so device is charging.
+ && mReports[mPeriodIndex].currentBatteryLevel < newBatteryLevel
+ && mReports[mPeriodIndex].cumulativeBatteryDischarge >= 25;
+ final boolean reportLongEnough = mReports[mPeriodIndex] != null
+ // Battery level is increasing, so device is charging.
+ && mReports[mPeriodIndex].currentBatteryLevel < newBatteryLevel
+ && mReports[mPeriodIndex].screenOffDurationMs >= MIN_REPORT_DURATION_FOR_RESET;
+ final boolean shouldStartNewReport = deviceDischargedEnough || reportLongEnough;
+ if (shouldStartNewReport) {
mPeriodIndex = (mPeriodIndex + 1) % NUM_PERIODS_TO_RETAIN;
if (mReports[mPeriodIndex] != null) {
final Report report = mReports[mPeriodIndex];
report.clear();
report.currentBatteryLevel = newBatteryLevel;
+ report.bsScreenOffRealtimeBase = getLatestBatteryScreenOffRealtimeMs();
+ report.bsScreenOffDischargeMahBase = getLatestScreenOffDischargeMah();
return;
}
}
if (mReports[mPeriodIndex] == null) {
- Report report = new Report();
+ Report report = initializeReport();
mReports[mPeriodIndex] = report;
report.currentBatteryLevel = newBatteryLevel;
return;
@@ -145,13 +224,27 @@ public class Analyst {
final Report report = mReports[mPeriodIndex];
if (newBatteryLevel < report.currentBatteryLevel) {
report.cumulativeBatteryDischarge += (report.currentBatteryLevel - newBatteryLevel);
+
+ final long latestScreenOffRealtime = getLatestBatteryScreenOffRealtimeMs();
+ final long latestScreenOffDischargeMah = getLatestScreenOffDischargeMah();
+ if (report.bsScreenOffRealtimeBase > latestScreenOffRealtime) {
+ // BatteryStats reset
+ report.bsScreenOffRealtimeBase = 0;
+ report.bsScreenOffDischargeMahBase = 0;
+ }
+ report.screenOffDurationMs +=
+ (latestScreenOffRealtime - report.bsScreenOffRealtimeBase);
+ report.screenOffDischargeMah +=
+ (latestScreenOffDischargeMah - report.bsScreenOffDischargeMahBase);
+ report.bsScreenOffRealtimeBase = latestScreenOffRealtime;
+ report.bsScreenOffDischargeMahBase = latestScreenOffDischargeMah;
}
report.currentBatteryLevel = newBatteryLevel;
}
void noteTransaction(@NonNull Ledger.Transaction transaction) {
if (mReports[mPeriodIndex] == null) {
- mReports[mPeriodIndex] = new Report();
+ mReports[mPeriodIndex] = initializeReport();
}
final Report report = mReports[mPeriodIndex];
switch (getEventType(transaction.eventId)) {
@@ -191,6 +284,32 @@ public class Analyst {
mPeriodIndex = 0;
}
+ private long getLatestBatteryScreenOffRealtimeMs() {
+ try {
+ return mIBatteryStats.computeBatteryScreenOffRealtimeMs();
+ } catch (RemoteException e) {
+ // Shouldn't happen
+ return 0;
+ }
+ }
+
+ private long getLatestScreenOffDischargeMah() {
+ try {
+ return mIBatteryStats.getScreenOffDischargeMah();
+ } catch (RemoteException e) {
+ // Shouldn't happen
+ return 0;
+ }
+ }
+
+ @NonNull
+ private Report initializeReport() {
+ final Report report = new Report();
+ report.bsScreenOffRealtimeBase = getLatestBatteryScreenOffRealtimeMs();
+ report.bsScreenOffDischargeMahBase = getLatestScreenOffDischargeMah();
+ return report;
+ }
+
@NonNull
private String padStringWithSpaces(@NonNull String text, int targetLength) {
// Make sure to have at least one space on either side.
@@ -199,6 +318,8 @@ public class Analyst {
}
void dump(IndentingPrintWriter pw) {
+ final BatteryManagerInternal bmi = LocalServices.getService(BatteryManagerInternal.class);
+ final long batteryCapacityMah = bmi.getBatteryFullCharge() / 1000;
pw.println("Reports:");
pw.increaseIndent();
pw.print(" Total Discharge");
@@ -208,6 +329,7 @@ public class Analyst {
pw.print(padStringWithSpaces("Rewards (avg/reward : avg/discharge)", statColsLength));
pw.print(padStringWithSpaces("+Regs (avg/reg : avg/discharge)", statColsLength));
pw.print(padStringWithSpaces("-Regs (avg/reg : avg/discharge)", statColsLength));
+ pw.print(padStringWithSpaces("Bg drain estimate", statColsLength));
pw.println();
for (int r = 0; r < NUM_PERIODS_TO_RETAIN; ++r) {
final int idx = (mPeriodIndex - r + NUM_PERIODS_TO_RETAIN) % NUM_PERIODS_TO_RETAIN;
@@ -283,6 +405,15 @@ public class Analyst {
} else {
pw.print(padStringWithSpaces("N/A", statColsLength));
}
+ if (report.screenOffDurationMs > 0) {
+ pw.print(padStringWithSpaces(String.format("%d mAh (%.2f%%/hr)",
+ report.screenOffDischargeMah,
+ 1.0 * report.screenOffDischargeMah * HOUR_IN_MILLIS
+ / (batteryCapacityMah * report.screenOffDurationMs)),
+ statColsLength));
+ } else {
+ pw.print(padStringWithSpaces("N/A", statColsLength));
+ }
pw.println();
}
pw.decreaseIndent();
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java
index 625f99d64ef4..66f7c357d223 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java
@@ -18,24 +18,30 @@ package com.android.server.tare;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.tare.EconomyManager;
import android.provider.DeviceConfig;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
+import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
import libcore.util.EmptyArray;
/** Combines all enabled policies into one. */
public class CompleteEconomicPolicy extends EconomicPolicy {
+ private static final String TAG = "TARE-" + CompleteEconomicPolicy.class.getSimpleName();
+ private final CompleteInjector mInjector;
private final ArraySet<EconomicPolicy> mEnabledEconomicPolicies = new ArraySet<>();
/** Lazily populated set of actions covered by this policy. */
private final SparseArray<Action> mActions = new SparseArray<>();
/** Lazily populated set of rewards covered by this policy. */
private final SparseArray<Reward> mRewards = new SparseArray<>();
- private final int[] mCostModifiers;
+ private int mEnabledEconomicPolicyIds = 0;
+ private int[] mCostModifiers = EmptyArray.INT;
private long mInitialConsumptionLimit;
private long mHardConsumptionLimit;
@@ -47,11 +53,34 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
CompleteEconomicPolicy(@NonNull InternalResourceService irs,
@NonNull CompleteInjector injector) {
super(irs);
- if (injector.isPolicyEnabled(POLICY_AM)) {
- mEnabledEconomicPolicies.add(new AlarmManagerEconomicPolicy(irs, injector));
+ mInjector = injector;
+
+ if (mInjector.isPolicyEnabled(POLICY_ALARM, null)) {
+ mEnabledEconomicPolicyIds |= POLICY_ALARM;
+ mEnabledEconomicPolicies.add(new AlarmManagerEconomicPolicy(mIrs, mInjector));
}
- if (injector.isPolicyEnabled(POLICY_JS)) {
- mEnabledEconomicPolicies.add(new JobSchedulerEconomicPolicy(irs, injector));
+ if (mInjector.isPolicyEnabled(POLICY_JOB, null)) {
+ mEnabledEconomicPolicyIds |= POLICY_JOB;
+ mEnabledEconomicPolicies.add(new JobSchedulerEconomicPolicy(mIrs, mInjector));
+ }
+ }
+
+ @Override
+ void setup(@NonNull DeviceConfig.Properties properties) {
+ super.setup(properties);
+
+ mActions.clear();
+ mRewards.clear();
+
+ mEnabledEconomicPolicies.clear();
+ mEnabledEconomicPolicyIds = 0;
+ if (mInjector.isPolicyEnabled(POLICY_ALARM, properties)) {
+ mEnabledEconomicPolicyIds |= POLICY_ALARM;
+ mEnabledEconomicPolicies.add(new AlarmManagerEconomicPolicy(mIrs, mInjector));
+ }
+ if (mInjector.isPolicyEnabled(POLICY_JOB, properties)) {
+ mEnabledEconomicPolicyIds |= POLICY_JOB;
+ mEnabledEconomicPolicies.add(new JobSchedulerEconomicPolicy(mIrs, mInjector));
}
ArraySet<Integer> costModifiers = new ArraySet<>();
@@ -61,17 +90,8 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
costModifiers.add(s);
}
}
- mCostModifiers = new int[costModifiers.size()];
- for (int i = 0; i < costModifiers.size(); ++i) {
- mCostModifiers[i] = costModifiers.valueAt(i);
- }
+ mCostModifiers = ArrayUtils.convertToIntArray(costModifiers);
- updateLimits();
- }
-
- @Override
- void setup(@NonNull DeviceConfig.Properties properties) {
- super.setup(properties);
for (int i = 0; i < mEnabledEconomicPolicies.size(); ++i) {
mEnabledEconomicPolicies.valueAt(i).setup(properties);
}
@@ -170,11 +190,37 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
return reward;
}
+ boolean isPolicyEnabled(@Policy int policyId) {
+ return (mEnabledEconomicPolicyIds & policyId) == policyId;
+ }
+
+ int getEnabledPolicyIds() {
+ return mEnabledEconomicPolicyIds;
+ }
+
@VisibleForTesting
static class CompleteInjector extends Injector {
- boolean isPolicyEnabled(int policy) {
- return true;
+ boolean isPolicyEnabled(int policy, @Nullable DeviceConfig.Properties properties) {
+ final String key;
+ final boolean defaultEnable;
+ switch (policy) {
+ case POLICY_ALARM:
+ key = EconomyManager.KEY_ENABLE_POLICY_ALARM;
+ defaultEnable = EconomyManager.DEFAULT_ENABLE_POLICY_ALARM;
+ break;
+ case POLICY_JOB:
+ key = EconomyManager.KEY_ENABLE_POLICY_JOB_SCHEDULER;
+ defaultEnable = EconomyManager.DEFAULT_ENABLE_POLICY_JOB_SCHEDULER;
+ break;
+ default:
+ Slog.wtf(TAG, "Unknown policy: " + policy);
+ return false;
+ }
+ if (properties == null) {
+ return defaultEnable;
+ }
+ return properties.getBoolean(key, defaultEnable);
}
}
@@ -189,7 +235,10 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
pw.println("Cached actions:");
pw.increaseIndent();
for (int i = 0; i < mActions.size(); ++i) {
- dumpAction(pw, mActions.valueAt(i));
+ final Action action = mActions.valueAt(i);
+ if (action != null) {
+ dumpAction(pw, action);
+ }
}
pw.decreaseIndent();
@@ -197,7 +246,10 @@ public class CompleteEconomicPolicy extends EconomicPolicy {
pw.println("Cached rewards:");
pw.increaseIndent();
for (int i = 0; i < mRewards.size(); ++i) {
- dumpReward(pw, mRewards.valueAt(i));
+ final Reward reward = mRewards.valueAt(i);
+ if (reward != null) {
+ dumpReward(pw, reward);
+ }
}
pw.decreaseIndent();
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java
index 7391bcfa8d88..008dcb8edf63 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java
@@ -57,9 +57,10 @@ public abstract class EconomicPolicy {
private static final int SHIFT_POLICY = 28;
static final int MASK_POLICY = 0b11 << SHIFT_POLICY;
+ static final int ALL_POLICIES = MASK_POLICY;
// Reserve 0 for the base/common policy.
- static final int POLICY_AM = 1 << SHIFT_POLICY;
- static final int POLICY_JS = 2 << SHIFT_POLICY;
+ public static final int POLICY_ALARM = 1 << SHIFT_POLICY;
+ public static final int POLICY_JOB = 2 << SHIFT_POLICY;
static final int MASK_EVENT = -1 ^ (MASK_TYPE | MASK_POLICY);
@@ -115,6 +116,15 @@ public abstract class EconomicPolicy {
}
@IntDef({
+ ALL_POLICIES,
+ POLICY_ALARM,
+ POLICY_JOB,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Policy {
+ }
+
+ @IntDef({
REWARD_TOP_ACTIVITY,
REWARD_NOTIFICATION_SEEN,
REWARD_NOTIFICATION_INTERACTION,
@@ -342,7 +352,7 @@ public abstract class EconomicPolicy {
@NonNull
static String actionToString(int eventId) {
switch (eventId & MASK_POLICY) {
- case POLICY_AM:
+ case POLICY_ALARM:
switch (eventId) {
case AlarmManagerEconomicPolicy.ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE:
return "ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE";
@@ -365,7 +375,7 @@ public abstract class EconomicPolicy {
}
break;
- case POLICY_JS:
+ case POLICY_JOB:
switch (eventId) {
case JobSchedulerEconomicPolicy.ACTION_JOB_MAX_START:
return "JOB_MAX_START";
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
index 0fa0c47e1b49..716769c21afc 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomyManagerInternal.java
@@ -138,6 +138,9 @@ public interface EconomyManagerInternal {
/** Returns true if TARE is enabled. */
boolean isEnabled();
+ /** Returns true if TARE and the specified policy are enabled. */
+ boolean isEnabled(@EconomicPolicy.Policy int policyId);
+
/**
* Register an {@link AffordabilityChangeListener} to track when an app's ability to afford the
* indicated bill changes.
@@ -155,7 +158,8 @@ public interface EconomyManagerInternal {
/**
* Register a {@link TareStateChangeListener} to track when TARE's state changes.
*/
- void registerTareStateChangeListener(@NonNull TareStateChangeListener listener);
+ void registerTareStateChangeListener(@NonNull TareStateChangeListener listener,
+ @EconomicPolicy.Policy int policyId);
/**
* Unregister a {@link TareStateChangeListener} from being notified when TARE's state changes.
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index 4a26d213a48a..dd0a19433683 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -30,6 +30,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.AlarmManager;
import android.app.AppOpsManager;
+import android.app.tare.EconomyManager;
import android.app.tare.IEconomyManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
@@ -82,7 +83,6 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
-import java.util.concurrent.CopyOnWriteArraySet;
/**
* Responsible for handling app's ARC count based on events, ensuring ARCs are credited when
@@ -112,6 +112,19 @@ public class InternalResourceService extends SystemService {
* limit).
*/
private static final int QUANTITATIVE_EASING_BATTERY_THRESHOLD = 50;
+ /**
+ * The battery level above which we may consider adjusting the desired stock level.
+ */
+ private static final int STOCK_RECALCULATION_BATTERY_THRESHOLD = 80;
+ /**
+ * The amount of time to wait before considering recalculating the desired stock level.
+ */
+ private static final long STOCK_RECALCULATION_DELAY_MS = 16 * HOUR_IN_MILLIS;
+ /**
+ * The minimum amount of time we must have background drain for before considering
+ * recalculating the desired stock level.
+ */
+ private static final long STOCK_RECALCULATION_MIN_DATA_DURATION_MS = 8 * HOUR_IN_MILLIS;
private static final int PACKAGE_QUERY_FLAGS =
PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
| PackageManager.MATCH_APEX;
@@ -148,8 +161,9 @@ public class InternalResourceService extends SystemService {
@GuardedBy("mPackageToUidCache")
private final SparseArrayMap<String, Integer> mPackageToUidCache = new SparseArrayMap<>();
- private final CopyOnWriteArraySet<TareStateChangeListener> mStateChangeListeners =
- new CopyOnWriteArraySet<>();
+ @GuardedBy("mStateChangeListeners")
+ private final SparseSetArray<TareStateChangeListener> mStateChangeListeners =
+ new SparseSetArray<>();
/**
* List of packages that are fully restricted and shouldn't be allowed to run in the background.
@@ -177,6 +191,9 @@ public class InternalResourceService extends SystemService {
@GuardedBy("mLock")
private int mCurrentBatteryLevel;
+ // TODO(250007395): make configurable per device
+ private final int mTargetBackgroundBatteryLifeHours;
+
private final IAppOpsCallback mApbListener = new IAppOpsCallback.Stub() {
@Override
public void opChanged(int op, int uid, String packageName) {
@@ -290,6 +307,7 @@ public class InternalResourceService extends SystemService {
private static final int MSG_SCHEDULE_UNUSED_WEALTH_RECLAMATION_EVENT = 1;
private static final int MSG_PROCESS_USAGE_EVENT = 2;
private static final int MSG_NOTIFY_STATE_CHANGE_LISTENERS = 3;
+ private static final int MSG_NOTIFY_STATE_CHANGE_LISTENER = 4;
private static final String ALARM_TAG_WEALTH_RECLAMATION = "*tare.reclamation*";
/**
@@ -316,6 +334,11 @@ public class InternalResourceService extends SystemService {
mConfigObserver = new ConfigObserver(mHandler, context);
+ mTargetBackgroundBatteryLifeHours =
+ mPackageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)
+ ? 200 // ~ 0.5%/hr
+ : 100; // ~ 1%/hr
+
publishLocalService(EconomyManagerInternal.class, new LocalService());
}
@@ -421,6 +444,12 @@ public class InternalResourceService extends SystemService {
return mIsEnabled;
}
+ boolean isEnabled(int policyId) {
+ synchronized (mLock) {
+ return isEnabled() && mCompleteEconomicPolicy.isPolicyEnabled(policyId);
+ }
+ }
+
boolean isPackageExempted(final int userId, @NonNull String pkgName) {
synchronized (mLock) {
return mExemptedApps.contains(pkgName);
@@ -461,6 +490,9 @@ public class InternalResourceService extends SystemService {
mAnalyst.noteBatteryLevelChange(newBatteryLevel);
final boolean increased = newBatteryLevel > mCurrentBatteryLevel;
if (increased) {
+ if (newBatteryLevel >= STOCK_RECALCULATION_BATTERY_THRESHOLD) {
+ maybeAdjustDesiredStockLevelLocked();
+ }
mAgent.distributeBasicIncomeLocked(newBatteryLevel);
} else if (newBatteryLevel == mCurrentBatteryLevel) {
// The broadcast is also sent when the plug type changes...
@@ -623,6 +655,10 @@ public class InternalResourceService extends SystemService {
*/
@GuardedBy("mLock")
void maybePerformQuantitativeEasingLocked() {
+ if (mConfigObserver.ENABLE_TIP3) {
+ maybeAdjustDesiredStockLevelLocked();
+ return;
+ }
// We don't need to increase the limit if the device runs out of consumable credits
// when the battery is low.
final long remainingConsumableCakes = mScribe.getRemainingConsumableCakesLocked();
@@ -643,6 +679,68 @@ public class InternalResourceService extends SystemService {
}
}
+ /**
+ * Adjust the consumption limit based on historical data and the target battery drain.
+ */
+ @GuardedBy("mLock")
+ void maybeAdjustDesiredStockLevelLocked() {
+ if (!mConfigObserver.ENABLE_TIP3) {
+ return;
+ }
+ // Don't adjust the limit too often or while the battery is low.
+ final long now = getCurrentTimeMillis();
+ if ((now - mScribe.getLastStockRecalculationTimeLocked()) < STOCK_RECALCULATION_DELAY_MS
+ || mCurrentBatteryLevel <= STOCK_RECALCULATION_BATTERY_THRESHOLD) {
+ return;
+ }
+
+ // For now, use screen off battery drain as a proxy for background battery drain.
+ // TODO: get more accurate background battery drain numbers
+ final long totalScreenOffDurationMs = mAnalyst.getBatteryScreenOffDurationMs();
+ if (totalScreenOffDurationMs < STOCK_RECALCULATION_MIN_DATA_DURATION_MS) {
+ return;
+ }
+ final long totalDischargeMah = mAnalyst.getBatteryScreenOffDischargeMah();
+ final long batteryCapacityMah = mBatteryManagerInternal.getBatteryFullCharge() / 1000;
+ final long estimatedLifeHours = batteryCapacityMah * totalScreenOffDurationMs
+ / totalDischargeMah / HOUR_IN_MILLIS;
+ final long percentageOfTarget =
+ 100 * estimatedLifeHours / mTargetBackgroundBatteryLifeHours;
+ if (DEBUG) {
+ Slog.d(TAG, "maybeAdjustDesiredStockLevelLocked:"
+ + " screenOffMs=" + totalScreenOffDurationMs
+ + " dischargeMah=" + totalDischargeMah
+ + " capacityMah=" + batteryCapacityMah
+ + " estimatedLifeHours=" + estimatedLifeHours
+ + " %ofTarget=" + percentageOfTarget);
+ }
+ final long currentConsumptionLimit = mScribe.getSatiatedConsumptionLimitLocked();
+ final long newConsumptionLimit;
+ if (percentageOfTarget > 105) {
+ // The stock is too low. We're doing pretty well. We can increase the stock slightly
+ // to let apps do more work in the background.
+ newConsumptionLimit = Math.min((long) (currentConsumptionLimit * 1.01),
+ mCompleteEconomicPolicy.getHardSatiatedConsumptionLimit());
+ } else if (percentageOfTarget < 100) {
+ // The stock is too high IMO. We're below the target. Decrease the stock to reduce
+ // background work.
+ newConsumptionLimit = Math.max((long) (currentConsumptionLimit * .98),
+ mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit());
+ } else {
+ // The stock is just right.
+ return;
+ }
+ // TODO(250007191): calculate and log implied service level
+ if (newConsumptionLimit != currentConsumptionLimit) {
+ Slog.i(TAG, "Adjusting consumption limit from " + cakeToString(currentConsumptionLimit)
+ + " to " + cakeToString(newConsumptionLimit)
+ + " because drain was " + percentageOfTarget + "% of target");
+ mScribe.setConsumptionLimitLocked(newConsumptionLimit);
+ adjustCreditSupplyLocked(/* allowIncrease */ true);
+ mScribe.setLastStockRecalculationTimeLocked(now);
+ }
+ }
+
void postAffordabilityChanged(final int userId, @NonNull final String pkgName,
@NonNull Agent.ActionAffordabilityNote affordabilityNote) {
if (DEBUG) {
@@ -994,9 +1092,30 @@ public class InternalResourceService extends SystemService {
}
break;
+ case MSG_NOTIFY_STATE_CHANGE_LISTENER: {
+ final int policy = msg.arg1;
+ final TareStateChangeListener listener = (TareStateChangeListener) msg.obj;
+ listener.onTareEnabledStateChanged(isEnabled(policy));
+ }
+ break;
+
case MSG_NOTIFY_STATE_CHANGE_LISTENERS: {
- for (TareStateChangeListener listener : mStateChangeListeners) {
- listener.onTareEnabledStateChanged(mIsEnabled);
+ final int changedPolicies = msg.arg1;
+ synchronized (mStateChangeListeners) {
+ final int size = mStateChangeListeners.size();
+ for (int l = 0; l < size; ++l) {
+ final int policy = mStateChangeListeners.keyAt(l);
+ if ((policy & changedPolicies) == 0) {
+ continue;
+ }
+ final ArraySet<TareStateChangeListener> listeners =
+ mStateChangeListeners.get(policy);
+ final boolean isEnabled = isEnabled(policy);
+ for (int p = listeners.size() - 1; p >= 0; --p) {
+ final TareStateChangeListener listener = listeners.valueAt(p);
+ listener.onTareEnabledStateChanged(isEnabled);
+ }
+ }
}
}
break;
@@ -1101,16 +1220,28 @@ public class InternalResourceService extends SystemService {
}
@Override
- public void registerTareStateChangeListener(@NonNull TareStateChangeListener listener) {
+ public void registerTareStateChangeListener(@NonNull TareStateChangeListener listener,
+ int policyId) {
if (!isTareSupported()) {
return;
}
- mStateChangeListeners.add(listener);
+ synchronized (mStateChangeListeners) {
+ if (mStateChangeListeners.add(policyId, listener)) {
+ mHandler.obtainMessage(MSG_NOTIFY_STATE_CHANGE_LISTENER, policyId, 0, listener)
+ .sendToTarget();
+ }
+ }
}
@Override
public void unregisterTareStateChangeListener(@NonNull TareStateChangeListener listener) {
- mStateChangeListeners.remove(listener);
+ synchronized (mStateChangeListeners) {
+ for (int i = mStateChangeListeners.size() - 1; i >= 0; --i) {
+ final ArraySet<TareStateChangeListener> listeners =
+ mStateChangeListeners.get(mStateChangeListeners.keyAt(i));
+ listeners.remove(listener);
+ }
+ }
}
@Override
@@ -1175,6 +1306,11 @@ public class InternalResourceService extends SystemService {
}
@Override
+ public boolean isEnabled(int policyId) {
+ return InternalResourceService.this.isEnabled(policyId);
+ }
+
+ @Override
public void noteInstantaneousEvent(int userId, @NonNull String pkgName, int eventId,
@Nullable String tag) {
if (!mIsEnabled) {
@@ -1213,7 +1349,12 @@ public class InternalResourceService extends SystemService {
private class ConfigObserver extends ContentObserver
implements DeviceConfig.OnPropertiesChangedListener {
- private static final String KEY_DC_ENABLE_TARE = "enable_tare";
+ private static final String KEY_ENABLE_TIP3 = "enable_tip3";
+
+ private static final boolean DEFAULT_ENABLE_TIP3 = true;
+
+ /** Use a target background battery drain rate to determine consumption limits. */
+ public boolean ENABLE_TIP3 = DEFAULT_ENABLE_TIP3;
private final ContentResolver mContentResolver;
@@ -1261,12 +1402,16 @@ public class InternalResourceService extends SystemService {
continue;
}
switch (name) {
- case KEY_DC_ENABLE_TARE:
+ case EconomyManager.KEY_ENABLE_TARE:
updateEnabledStatus();
break;
+ case KEY_ENABLE_TIP3:
+ ENABLE_TIP3 = properties.getBoolean(name, DEFAULT_ENABLE_TIP3);
+ break;
default:
if (!economicPolicyUpdated
- && (name.startsWith("am") || name.startsWith("js"))) {
+ && (name.startsWith("am") || name.startsWith("js")
+ || name.startsWith("enable_policy"))) {
updateEconomicPolicy();
economicPolicyUpdated = true;
}
@@ -1278,7 +1423,7 @@ public class InternalResourceService extends SystemService {
private void updateEnabledStatus() {
// User setting should override DeviceConfig setting.
final boolean isTareEnabledDC = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_TARE,
- KEY_DC_ENABLE_TARE, Settings.Global.DEFAULT_ENABLE_TARE == 1);
+ EconomyManager.KEY_ENABLE_TARE, EconomyManager.DEFAULT_ENABLE_TARE);
final boolean isTareEnabled = isTareSupported()
&& Settings.Global.getInt(mContentResolver,
Settings.Global.ENABLE_TARE, isTareEnabledDC ? 1 : 0) == 1;
@@ -1289,7 +1434,9 @@ public class InternalResourceService extends SystemService {
} else {
tearDownEverything();
}
- mHandler.sendEmptyMessage(MSG_NOTIFY_STATE_CHANGE_LISTENERS);
+ mHandler.obtainMessage(
+ MSG_NOTIFY_STATE_CHANGE_LISTENERS, EconomicPolicy.ALL_POLICIES, 0)
+ .sendToTarget();
}
}
@@ -1298,9 +1445,10 @@ public class InternalResourceService extends SystemService {
final long initialLimit =
mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit();
final long hardLimit = mCompleteEconomicPolicy.getHardSatiatedConsumptionLimit();
+ final int oldEnabledPolicies = mCompleteEconomicPolicy.getEnabledPolicyIds();
mCompleteEconomicPolicy.tearDown();
mCompleteEconomicPolicy = new CompleteEconomicPolicy(InternalResourceService.this);
- if (mIsEnabled && mBootPhase >= PHASE_SYSTEM_SERVICES_READY) {
+ if (mIsEnabled && mBootPhase >= PHASE_THIRD_PARTY_APPS_CAN_START) {
mCompleteEconomicPolicy.setup(getAllDeviceConfigProperties());
if (initialLimit != mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit()
|| hardLimit
@@ -1310,6 +1458,13 @@ public class InternalResourceService extends SystemService {
mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit());
}
mAgent.onPricingChangedLocked();
+ final int newEnabledPolicies = mCompleteEconomicPolicy.getEnabledPolicyIds();
+ if (oldEnabledPolicies != newEnabledPolicies) {
+ final int changedPolicies = oldEnabledPolicies ^ newEnabledPolicies;
+ mHandler.obtainMessage(
+ MSG_NOTIFY_STATE_CHANGE_LISTENERS, changedPolicies, 0)
+ .sendToTarget();
+ }
}
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java
index 322e824286d5..71c6d099ac77 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java
@@ -133,19 +133,19 @@ import android.util.SparseArray;
public class JobSchedulerEconomicPolicy extends EconomicPolicy {
private static final String TAG = "TARE- " + JobSchedulerEconomicPolicy.class.getSimpleName();
- public static final int ACTION_JOB_MAX_START = TYPE_ACTION | POLICY_JS | 0;
- public static final int ACTION_JOB_MAX_RUNNING = TYPE_ACTION | POLICY_JS | 1;
- public static final int ACTION_JOB_HIGH_START = TYPE_ACTION | POLICY_JS | 2;
- public static final int ACTION_JOB_HIGH_RUNNING = TYPE_ACTION | POLICY_JS | 3;
- public static final int ACTION_JOB_DEFAULT_START = TYPE_ACTION | POLICY_JS | 4;
- public static final int ACTION_JOB_DEFAULT_RUNNING = TYPE_ACTION | POLICY_JS | 5;
- public static final int ACTION_JOB_LOW_START = TYPE_ACTION | POLICY_JS | 6;
- public static final int ACTION_JOB_LOW_RUNNING = TYPE_ACTION | POLICY_JS | 7;
- public static final int ACTION_JOB_MIN_START = TYPE_ACTION | POLICY_JS | 8;
- public static final int ACTION_JOB_MIN_RUNNING = TYPE_ACTION | POLICY_JS | 9;
- public static final int ACTION_JOB_TIMEOUT = TYPE_ACTION | POLICY_JS | 10;
-
- public static final int REWARD_APP_INSTALL = TYPE_REWARD | POLICY_JS | 0;
+ public static final int ACTION_JOB_MAX_START = TYPE_ACTION | POLICY_JOB | 0;
+ public static final int ACTION_JOB_MAX_RUNNING = TYPE_ACTION | POLICY_JOB | 1;
+ public static final int ACTION_JOB_HIGH_START = TYPE_ACTION | POLICY_JOB | 2;
+ public static final int ACTION_JOB_HIGH_RUNNING = TYPE_ACTION | POLICY_JOB | 3;
+ public static final int ACTION_JOB_DEFAULT_START = TYPE_ACTION | POLICY_JOB | 4;
+ public static final int ACTION_JOB_DEFAULT_RUNNING = TYPE_ACTION | POLICY_JOB | 5;
+ public static final int ACTION_JOB_LOW_START = TYPE_ACTION | POLICY_JOB | 6;
+ public static final int ACTION_JOB_LOW_RUNNING = TYPE_ACTION | POLICY_JOB | 7;
+ public static final int ACTION_JOB_MIN_START = TYPE_ACTION | POLICY_JOB | 8;
+ public static final int ACTION_JOB_MIN_RUNNING = TYPE_ACTION | POLICY_JOB | 9;
+ public static final int ACTION_JOB_TIMEOUT = TYPE_ACTION | POLICY_JOB | 10;
+
+ public static final int REWARD_APP_INSTALL = TYPE_REWARD | POLICY_JOB | 0;
private static final int[] COST_MODIFIERS = new int[]{
COST_MODIFIER_CHARGING,
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/README.md b/apex/jobscheduler/service/java/com/android/server/tare/README.md
index e338ed1c6987..8d25ecce8431 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/README.md
+++ b/apex/jobscheduler/service/java/com/android/server/tare/README.md
@@ -80,9 +80,9 @@ consumption limit, then the available resources are decreased to match the scale
Regulations are unique events invoked by the ~~government~~ system in order to get the whole economy
moving smoothly.
-# Previous Implementations
+# Significant Changes
-## V0
+## Tare Improvement Proposal #1 (TIP1)
The initial implementation/proposal combined the supply of resources with the allocation in a single
mechanism. It defined the maximum number of resources (ARCs) available at a time, and then divided
@@ -98,10 +98,25 @@ allocated as part of the rewards. There were several problems with that mechanis
These problems effectively meant that misallocation was a big problem, demand wasn't well reflected,
and some apps may not have been able to perform work even though they otherwise should have been.
-Tare Improvement Proposal #1 (TIP1) separated allocation (to apps) from supply (by the system) and
+TIP1 separated allocation (to apps) from supply (by the system) and
allowed apps to accrue credits as appropriate while still limiting the total number of credits
consumed.
+## Tare Improvement Proposal #3 (TIP3)
+
+TIP1 introduced Consumption Limits, which control the total number of ARCs that can be used to
+perform actions, based on the production costs of each action. The Consumption Limits were initially
+determined manually, but could increase in the system if apps used the full consumption limit before
+the device had drained to 50% battery. As with any system that relies on manually deciding
+parameters, the only mechanism to identify an optimal value is through experimentation, which can
+take many iterations and requires extended periods of time to observe results. The limits are also
+chosen and adjusted without consideration of the resulting battery drain of each possible value. In
+addition, having the system potentially increase the limit without considering a decrease introduced
+potential for battery life to get worse as time goes on and the user installed more background-work
+demanding apps.
+
+TIP3 uses a target background battery drain rate to dynamically adjust the Consumption Limit.
+
# Potential Future Changes
These are some ideas for further changes. There's no guarantee that they'll be implemented.
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java b/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
index bd4fd72b78ce..27d00b76f452 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/Scribe.java
@@ -84,6 +84,8 @@ public class Scribe {
private static final String XML_ATTR_USER_ID = "userId";
private static final String XML_ATTR_VERSION = "version";
private static final String XML_ATTR_LAST_RECLAMATION_TIME = "lastReclamationTime";
+ private static final String XML_ATTR_LAST_STOCK_RECALCULATION_TIME =
+ "lastStockRecalculationTime";
private static final String XML_ATTR_REMAINING_CONSUMABLE_CAKES = "remainingConsumableCakes";
private static final String XML_ATTR_CONSUMPTION_LIMIT = "consumptionLimit";
private static final String XML_ATTR_PR_DISCHARGE = "discharge";
@@ -98,6 +100,8 @@ public class Scribe {
private static final String XML_ATTR_PR_NUM_POS_REGULATIONS = "numPosRegulations";
private static final String XML_ATTR_PR_NEG_REGULATIONS = "negRegulations";
private static final String XML_ATTR_PR_NUM_NEG_REGULATIONS = "numNegRegulations";
+ private static final String XML_ATTR_PR_SCREEN_OFF_DURATION_MS = "screenOffDurationMs";
+ private static final String XML_ATTR_PR_SCREEN_OFF_DISCHARGE_MAH = "screenOffDischargeMah";
/** Version of the file schema. */
private static final int STATE_FILE_VERSION = 0;
@@ -111,6 +115,8 @@ public class Scribe {
@GuardedBy("mIrs.getLock()")
private long mLastReclamationTime;
@GuardedBy("mIrs.getLock()")
+ private long mLastStockRecalculationTime;
+ @GuardedBy("mIrs.getLock()")
private long mSatiatedConsumptionLimit;
@GuardedBy("mIrs.getLock()")
private long mRemainingConsumableCakes;
@@ -173,6 +179,11 @@ public class Scribe {
}
@GuardedBy("mIrs.getLock()")
+ long getLastStockRecalculationTimeLocked() {
+ return mLastStockRecalculationTime;
+ }
+
+ @GuardedBy("mIrs.getLock()")
@NonNull
Ledger getLedgerLocked(final int userId, @NonNull final String pkgName) {
Ledger ledger = mLedgers.get(userId, pkgName);
@@ -281,6 +292,8 @@ public class Scribe {
case XML_TAG_HIGH_LEVEL_STATE:
mLastReclamationTime =
parser.getAttributeLong(null, XML_ATTR_LAST_RECLAMATION_TIME);
+ mLastStockRecalculationTime = parser.getAttributeLong(null,
+ XML_ATTR_LAST_STOCK_RECALCULATION_TIME, 0);
mSatiatedConsumptionLimit =
parser.getAttributeLong(null, XML_ATTR_CONSUMPTION_LIMIT,
mIrs.getInitialSatiatedConsumptionLimitLocked());
@@ -337,6 +350,12 @@ public class Scribe {
}
@GuardedBy("mIrs.getLock()")
+ void setLastStockRecalculationTimeLocked(long time) {
+ mLastStockRecalculationTime = time;
+ postWrite();
+ }
+
+ @GuardedBy("mIrs.getLock()")
void tearDownLocked() {
TareHandlerThread.getHandler().removeCallbacks(mCleanRunnable);
TareHandlerThread.getHandler().removeCallbacks(mWriteRunnable);
@@ -504,7 +523,6 @@ public class Scribe {
return earliestEndTime;
}
-
/**
* @param parser Xml parser at the beginning of a {@link #XML_TAG_PERIOD_REPORT} tag. The next
* "parser.next()" call will take the parser into the body of the report tag.
@@ -531,6 +549,10 @@ public class Scribe {
parser.getAttributeLong(null, XML_ATTR_PR_NEG_REGULATIONS);
report.numNegativeRegulations =
parser.getAttributeInt(null, XML_ATTR_PR_NUM_NEG_REGULATIONS);
+ report.screenOffDurationMs =
+ parser.getAttributeLong(null, XML_ATTR_PR_SCREEN_OFF_DURATION_MS, 0);
+ report.screenOffDischargeMah =
+ parser.getAttributeLong(null, XML_ATTR_PR_SCREEN_OFF_DISCHARGE_MAH, 0);
return report;
}
@@ -606,6 +628,8 @@ public class Scribe {
out.startTag(null, XML_TAG_HIGH_LEVEL_STATE);
out.attributeLong(null, XML_ATTR_LAST_RECLAMATION_TIME, mLastReclamationTime);
+ out.attributeLong(null,
+ XML_ATTR_LAST_STOCK_RECALCULATION_TIME, mLastStockRecalculationTime);
out.attributeLong(null, XML_ATTR_CONSUMPTION_LIMIT, mSatiatedConsumptionLimit);
out.attributeLong(null, XML_ATTR_REMAINING_CONSUMABLE_CAKES,
mRemainingConsumableCakes);
@@ -718,6 +742,8 @@ public class Scribe {
out.attributeInt(null, XML_ATTR_PR_NUM_POS_REGULATIONS, report.numPositiveRegulations);
out.attributeLong(null, XML_ATTR_PR_NEG_REGULATIONS, report.cumulativeNegativeRegulations);
out.attributeInt(null, XML_ATTR_PR_NUM_NEG_REGULATIONS, report.numNegativeRegulations);
+ out.attributeLong(null, XML_ATTR_PR_SCREEN_OFF_DURATION_MS, report.screenOffDurationMs);
+ out.attributeLong(null, XML_ATTR_PR_SCREEN_OFF_DISCHARGE_MAH, report.screenOffDischargeMah);
out.endTag(null, XML_TAG_PERIOD_REPORT);
}
diff --git a/apex/jobscheduler/service/jni/com_android_server_alarm_AlarmManagerService.cpp b/apex/jobscheduler/service/jni/com_android_server_alarm_AlarmManagerService.cpp
index 8f9e187a7a93..b2ed4d47adf4 100644
--- a/apex/jobscheduler/service/jni/com_android_server_alarm_AlarmManagerService.cpp
+++ b/apex/jobscheduler/service/jni/com_android_server_alarm_AlarmManagerService.cpp
@@ -76,19 +76,17 @@ typedef std::array<int, N_ANDROID_TIMERFDS> TimerFds;
class AlarmImpl
{
public:
- AlarmImpl(const TimerFds &fds, int epollfd, const std::string &rtc_dev)
- : fds{fds}, epollfd{epollfd}, rtc_dev{rtc_dev} {}
+ AlarmImpl(const TimerFds &fds, int epollfd)
+ : fds{fds}, epollfd{epollfd} {}
~AlarmImpl();
int set(int type, struct timespec *ts);
- int setTime(struct timeval *tv);
int waitForAlarm();
int getTime(int type, struct itimerspec *spec);
private:
const TimerFds fds;
const int epollfd;
- std::string rtc_dev;
};
AlarmImpl::~AlarmImpl()
@@ -131,43 +129,6 @@ int AlarmImpl::getTime(int type, struct itimerspec *spec)
return timerfd_gettime(fds[type], spec);
}
-int AlarmImpl::setTime(struct timeval *tv)
-{
- if (settimeofday(tv, NULL) == -1) {
- ALOGV("settimeofday() failed: %s", strerror(errno));
- return -1;
- }
-
- android::base::unique_fd fd{open(rtc_dev.c_str(), O_RDWR)};
- if (!fd.ok()) {
- ALOGE("Unable to open %s: %s", rtc_dev.c_str(), strerror(errno));
- return -1;
- }
-
- struct tm tm;
- if (!gmtime_r(&tv->tv_sec, &tm)) {
- ALOGV("gmtime_r() failed: %s", strerror(errno));
- return -1;
- }
-
- struct rtc_time rtc = {};
- rtc.tm_sec = tm.tm_sec;
- rtc.tm_min = tm.tm_min;
- rtc.tm_hour = tm.tm_hour;
- rtc.tm_mday = tm.tm_mday;
- rtc.tm_mon = tm.tm_mon;
- rtc.tm_year = tm.tm_year;
- rtc.tm_wday = tm.tm_wday;
- rtc.tm_yday = tm.tm_yday;
- rtc.tm_isdst = tm.tm_isdst;
- if (ioctl(fd, RTC_SET_TIME, &rtc) == -1) {
- ALOGV("RTC_SET_TIME ioctl failed: %s", strerror(errno));
- return -1;
- }
-
- return 0;
-}
-
int AlarmImpl::waitForAlarm()
{
epoll_event events[N_ANDROID_TIMERFDS];
@@ -198,28 +159,6 @@ int AlarmImpl::waitForAlarm()
return result;
}
-static jint android_server_alarm_AlarmManagerService_setKernelTime(JNIEnv*, jobject, jlong nativeData, jlong millis)
-{
- AlarmImpl *impl = reinterpret_cast<AlarmImpl *>(nativeData);
-
- if (millis <= 0 || millis / 1000LL >= std::numeric_limits<time_t>::max()) {
- return -1;
- }
-
- struct timeval tv;
- tv.tv_sec = (millis / 1000LL);
- tv.tv_usec = ((millis % 1000LL) * 1000LL);
-
- ALOGD("Setting time of day to sec=%ld", tv.tv_sec);
-
- int ret = impl->setTime(&tv);
- if (ret < 0) {
- ALOGW("Unable to set rtc to %ld: %s", tv.tv_sec, strerror(errno));
- ret = -1;
- }
- return ret;
-}
-
static jint android_server_alarm_AlarmManagerService_setKernelTimezone(JNIEnv*, jobject, jlong, jint minswest)
{
struct timezone tz;
@@ -287,19 +226,7 @@ static jlong android_server_alarm_AlarmManagerService_init(JNIEnv*, jobject)
}
}
- // Find the wall clock RTC. We expect this always to be /dev/rtc0, but
- // check the /dev/rtc symlink first so that legacy devices that don't use
- // rtc0 can add a symlink rather than need to carry a local patch to this
- // code.
- //
- // TODO: if you're reading this in a world where all devices are using the
- // GKI, you can remove the readlink and just assume /dev/rtc0.
- std::string dev_rtc;
- if (!android::base::Readlink("/dev/rtc", &dev_rtc)) {
- dev_rtc = "/dev/rtc0";
- }
-
- std::unique_ptr<AlarmImpl> alarm{new AlarmImpl(fds, epollfd, dev_rtc)};
+ std::unique_ptr<AlarmImpl> alarm{new AlarmImpl(fds, epollfd)};
for (size_t i = 0; i < fds.size(); i++) {
epoll_event event;
@@ -392,7 +319,6 @@ static const JNINativeMethod sMethods[] = {
{"close", "(J)V", (void*)android_server_alarm_AlarmManagerService_close},
{"set", "(JIJJ)I", (void*)android_server_alarm_AlarmManagerService_set},
{"waitForAlarm", "(J)I", (void*)android_server_alarm_AlarmManagerService_waitForAlarm},
- {"setKernelTime", "(JJ)I", (void*)android_server_alarm_AlarmManagerService_setKernelTime},
{"setKernelTimezone", "(JI)I", (void*)android_server_alarm_AlarmManagerService_setKernelTimezone},
{"getNextAlarm", "(JI)J", (void*)android_server_alarm_AlarmManagerService_getNextAlarm},
};
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 320e147c93a5..44311648da80 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -23,6 +23,7 @@
#include <cstring>
#include <filesystem>
#include <fstream>
+#include <limits>
#include <memory>
#include <ostream>
#include <string>
@@ -301,28 +302,42 @@ Status Idmap2Service::createFabricatedOverlay(
return ok();
}
-Status Idmap2Service::acquireFabricatedOverlayIterator() {
+Status Idmap2Service::acquireFabricatedOverlayIterator(int32_t* _aidl_return) {
+ std::lock_guard l(frro_iter_mutex_);
if (frro_iter_.has_value()) {
LOG(WARNING) << "active ffro iterator was not previously released";
}
frro_iter_ = std::filesystem::directory_iterator(kIdmapCacheDir);
+ if (frro_iter_id_ == std::numeric_limits<int32_t>::max()) {
+ frro_iter_id_ = 0;
+ } else {
+ ++frro_iter_id_;
+ }
+ *_aidl_return = frro_iter_id_;
return ok();
}
-Status Idmap2Service::releaseFabricatedOverlayIterator() {
+Status Idmap2Service::releaseFabricatedOverlayIterator(int32_t iteratorId) {
+ std::lock_guard l(frro_iter_mutex_);
if (!frro_iter_.has_value()) {
LOG(WARNING) << "no active ffro iterator to release";
+ } else if (frro_iter_id_ != iteratorId) {
+ LOG(WARNING) << "incorrect iterator id in a call to release";
} else {
- frro_iter_ = std::nullopt;
+ frro_iter_.reset();
}
return ok();
}
-Status Idmap2Service::nextFabricatedOverlayInfos(
+Status Idmap2Service::nextFabricatedOverlayInfos(int32_t iteratorId,
std::vector<os::FabricatedOverlayInfo>* _aidl_return) {
+ std::lock_guard l(frro_iter_mutex_);
+
constexpr size_t kMaxEntryCount = 100;
if (!frro_iter_.has_value()) {
return error("no active frro iterator");
+ } else if (frro_iter_id_ != iteratorId) {
+ return error("incorrect iterator id in a call to next");
}
size_t count = 0;
@@ -330,22 +345,22 @@ Status Idmap2Service::nextFabricatedOverlayInfos(
auto entry_iter_end = end(*frro_iter_);
for (; entry_iter != entry_iter_end && count < kMaxEntryCount; ++entry_iter) {
auto& entry = *entry_iter;
- if (!entry.is_regular_file() || !android::IsFabricatedOverlay(entry.path())) {
+ if (!entry.is_regular_file() || !android::IsFabricatedOverlay(entry.path().native())) {
continue;
}
- const auto overlay = FabricatedOverlayContainer::FromPath(entry.path());
+ const auto overlay = FabricatedOverlayContainer::FromPath(entry.path().native());
if (!overlay) {
LOG(WARNING) << "Failed to open '" << entry.path() << "': " << overlay.GetErrorMessage();
continue;
}
- const auto info = (*overlay)->GetManifestInfo();
+ auto info = (*overlay)->GetManifestInfo();
os::FabricatedOverlayInfo out_info;
- out_info.packageName = info.package_name;
- out_info.overlayName = info.name;
- out_info.targetPackageName = info.target_package;
- out_info.targetOverlayable = info.target_name;
+ out_info.packageName = std::move(info.package_name);
+ out_info.overlayName = std::move(info.name);
+ out_info.targetPackageName = std::move(info.target_package);
+ out_info.targetOverlayable = std::move(info.target_name);
out_info.path = entry.path();
_aidl_return->emplace_back(std::move(out_info));
count++;
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index c61e4bc98a54..cc8cc5f218d2 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -26,7 +26,10 @@
#include <filesystem>
#include <memory>
+#include <mutex>
+#include <optional>
#include <string>
+#include <variant>
#include <vector>
namespace android::os {
@@ -60,11 +63,11 @@ class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 {
binder::Status deleteFabricatedOverlay(const std::string& overlay_path,
bool* _aidl_return) override;
- binder::Status acquireFabricatedOverlayIterator() override;
+ binder::Status acquireFabricatedOverlayIterator(int32_t* _aidl_return) override;
- binder::Status releaseFabricatedOverlayIterator() override;
+ binder::Status releaseFabricatedOverlayIterator(int32_t iteratorId) override;
- binder::Status nextFabricatedOverlayInfos(
+ binder::Status nextFabricatedOverlayInfos(int32_t iteratorId,
std::vector<os::FabricatedOverlayInfo>* _aidl_return) override;
binder::Status dumpIdmap(const std::string& overlay_path, std::string* _aidl_return) override;
@@ -74,7 +77,9 @@ class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 {
// be able to be recalculated if idmap2 dies and restarts.
std::unique_ptr<idmap2::TargetResourceContainer> framework_apk_cache_;
+ int32_t frro_iter_id_ = 0;
std::optional<std::filesystem::directory_iterator> frro_iter_;
+ std::mutex frro_iter_mutex_;
template <typename T>
using MaybeUniquePtr = std::variant<std::unique_ptr<T>, T*>;
diff --git a/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl b/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl
index 0059cf293177..2bbfba97a6c6 100644
--- a/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl
+++ b/cmds/idmap2/idmap2d/aidl/services/android/os/IIdmap2.aidl
@@ -41,9 +41,9 @@ interface IIdmap2 {
@nullable FabricatedOverlayInfo createFabricatedOverlay(in FabricatedOverlayInternal overlay);
boolean deleteFabricatedOverlay(@utf8InCpp String path);
- void acquireFabricatedOverlayIterator();
- void releaseFabricatedOverlayIterator();
- List<FabricatedOverlayInfo> nextFabricatedOverlayInfos();
+ int acquireFabricatedOverlayIterator();
+ void releaseFabricatedOverlayIterator(int iteratorId);
+ List<FabricatedOverlayInfo> nextFabricatedOverlayInfos(int iteratorId);
@utf8InCpp String dumpIdmap(@utf8InCpp String overlayApkPath);
}
diff --git a/core/api/current.txt b/core/api/current.txt
index 9cfc161fb7e4..7a412d8e2a81 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9015,6 +9015,7 @@ package android.companion {
public final class CompanionDeviceManager {
method @RequiresPermission(anyOf={android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH, android.Manifest.permission.REQUEST_COMPANION_PROFILE_COMPUTER, android.Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING, android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION}, conditional=true) public void associate(@NonNull android.companion.AssociationRequest, @NonNull android.companion.CompanionDeviceManager.Callback, @Nullable android.os.Handler);
method @RequiresPermission(anyOf={android.Manifest.permission.REQUEST_COMPANION_PROFILE_WATCH, android.Manifest.permission.REQUEST_COMPANION_PROFILE_COMPUTER, android.Manifest.permission.REQUEST_COMPANION_PROFILE_APP_STREAMING, android.Manifest.permission.REQUEST_COMPANION_PROFILE_AUTOMOTIVE_PROJECTION}, conditional=true) public void associate(@NonNull android.companion.AssociationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.companion.CompanionDeviceManager.Callback);
+ method @Nullable public android.content.IntentSender buildAssociationCancellationIntent();
method @Nullable public android.content.IntentSender buildPermissionTransferUserConsentIntent(int) throws android.companion.DeviceNotAssociatedException;
method @Deprecated public void disassociate(@NonNull String);
method public void disassociate(int);
@@ -45192,6 +45193,14 @@ package android.text {
method public void getChars(int, int, char[], int);
}
+ public class GraphemeClusterSegmentFinder extends android.text.SegmentFinder {
+ ctor public GraphemeClusterSegmentFinder(@NonNull CharSequence, @NonNull android.text.TextPaint);
+ method public int nextEndBoundary(@IntRange(from=0) int);
+ method public int nextStartBoundary(@IntRange(from=0) int);
+ method public int previousEndBoundary(@IntRange(from=0) int);
+ method public int previousStartBoundary(@IntRange(from=0) int);
+ }
+
public class Html {
method public static String escapeHtml(CharSequence);
method @Deprecated public static android.text.Spanned fromHtml(String);
@@ -45321,6 +45330,7 @@ package android.text {
method public final int getParagraphLeft(int);
method public final int getParagraphRight(int);
method public float getPrimaryHorizontal(int);
+ method @Nullable public int[] getRangeForRect(@NonNull android.graphics.RectF, @NonNull android.text.SegmentFinder, @NonNull android.text.Layout.TextInclusionStrategy);
method public float getSecondaryHorizontal(int);
method public void getSelectionPath(int, int, android.graphics.Path);
method public final float getSpacingAdd();
@@ -45344,6 +45354,9 @@ package android.text {
field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
field public static final int HYPHENATION_FREQUENCY_NORMAL_FAST = 3; // 0x3
+ field @NonNull public static final android.text.Layout.TextInclusionStrategy INCLUSION_STRATEGY_ANY_OVERLAP;
+ field @NonNull public static final android.text.Layout.TextInclusionStrategy INCLUSION_STRATEGY_CONTAINS_ALL;
+ field @NonNull public static final android.text.Layout.TextInclusionStrategy INCLUSION_STRATEGY_CONTAINS_CENTER;
field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
}
@@ -45357,6 +45370,10 @@ package android.text {
public static class Layout.Directions {
}
+ @java.lang.FunctionalInterface public static interface Layout.TextInclusionStrategy {
+ method public boolean isSegmentInside(@NonNull android.graphics.RectF, @NonNull android.graphics.RectF);
+ }
+
@Deprecated public abstract class LoginFilter implements android.text.InputFilter {
method @Deprecated public CharSequence filter(CharSequence, int, int, android.text.Spanned, int, int);
method @Deprecated public abstract boolean isAllowed(char);
@@ -45433,6 +45450,15 @@ package android.text {
method public android.text.PrecomputedText.Params.Builder setTextDirection(@NonNull android.text.TextDirectionHeuristic);
}
+ public abstract class SegmentFinder {
+ ctor public SegmentFinder();
+ method public abstract int nextEndBoundary(@IntRange(from=0) int);
+ method public abstract int nextStartBoundary(@IntRange(from=0) int);
+ method public abstract int previousEndBoundary(@IntRange(from=0) int);
+ method public abstract int previousStartBoundary(@IntRange(from=0) int);
+ field public static final int DONE = -1; // 0xffffffff
+ }
+
public class Selection {
method public static boolean extendDown(android.text.Spannable, android.text.Layout);
method public static boolean extendLeft(android.text.Spannable, android.text.Layout);
@@ -45718,6 +45744,14 @@ package android.text {
method public void onTextChanged(CharSequence, int, int, int);
}
+ public class WordSegmentFinder extends android.text.SegmentFinder {
+ ctor public WordSegmentFinder(@NonNull CharSequence, @NonNull java.util.Locale);
+ method public int nextEndBoundary(@IntRange(from=0) int);
+ method public int nextStartBoundary(@IntRange(from=0) int);
+ method public int previousEndBoundary(@IntRange(from=0) int);
+ method public int previousStartBoundary(@IntRange(from=0) int);
+ }
+
}
package android.text.format {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 212e3581269a..422b6a389b05 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -8051,8 +8051,9 @@ public class Activity extends ContextThemeWrapper
resultData.prepareToLeaveProcess(this);
}
upIntent.prepareToLeaveProcess(this);
- return ActivityClient.getInstance().navigateUpTo(mToken, upIntent, resultCode,
- resultData);
+ String resolvedType = upIntent.resolveTypeIfNeeded(getContentResolver());
+ return ActivityClient.getInstance().navigateUpTo(mToken, upIntent, resolvedType,
+ resultCode, resultData);
} else {
return mParent.navigateUpToFromChild(this, upIntent);
}
diff --git a/core/java/android/app/ActivityClient.java b/core/java/android/app/ActivityClient.java
index 482f456b5d83..d1e6780e3618 100644
--- a/core/java/android/app/ActivityClient.java
+++ b/core/java/android/app/ActivityClient.java
@@ -141,11 +141,11 @@ public class ActivityClient {
}
}
- boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
+ boolean navigateUpTo(IBinder token, Intent destIntent, String resolvedType, int resultCode,
Intent resultData) {
try {
- return getActivityClientController().navigateUpTo(token, destIntent, resultCode,
- resultData);
+ return getActivityClientController().navigateUpTo(token, destIntent, resolvedType,
+ resultCode, resultData);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 626b7d3cd5b1..8da9631a23b0 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -31,6 +31,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ActivityPresentationInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PermissionMethod;
+import android.content.pm.PermissionName;
import android.content.pm.UserInfo;
import android.net.Uri;
import android.os.Bundle;
@@ -294,7 +295,7 @@ public abstract class ActivityManagerInternal {
/** Checks if the calling binder pid as the permission. */
@PermissionMethod
- public abstract void enforceCallingPermission(String permission, String func);
+ public abstract void enforceCallingPermission(@PermissionName String permission, String func);
/** Returns the current user id. */
public abstract int getCurrentUserId();
diff --git a/core/java/android/app/IActivityClientController.aidl b/core/java/android/app/IActivityClientController.aidl
index f5e5cda9c639..9aa67bc51182 100644
--- a/core/java/android/app/IActivityClientController.aidl
+++ b/core/java/android/app/IActivityClientController.aidl
@@ -60,8 +60,8 @@ interface IActivityClientController {
in SizeConfigurationBuckets sizeConfigurations);
boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot);
boolean shouldUpRecreateTask(in IBinder token, in String destAffinity);
- boolean navigateUpTo(in IBinder token, in Intent target, int resultCode,
- in Intent resultData);
+ boolean navigateUpTo(in IBinder token, in Intent target, in String resolvedType,
+ int resultCode, in Intent resultData);
boolean releaseActivityInstance(in IBinder token);
boolean finishActivity(in IBinder token, int code, in Intent data, int finishTask);
boolean finishActivityAffinity(in IBinder token);
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 2bd36b8675e1..4142bceb2c45 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -30,6 +30,7 @@ import android.annotation.UserHandleAware;
import android.app.Activity;
import android.app.NotificationManager;
import android.app.PendingIntent;
+import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.ComponentName;
import android.content.Context;
@@ -367,6 +368,10 @@ public final class CompanionDeviceManager {
* recommended to do when an association is no longer relevant to avoid unnecessary battery
* and/or data drain resulting from special privileges that the association provides</p>
*
+ * <p>Note that if you use this api to associate with a Bluetooth device, please make sure
+ * to cancel your own Bluetooth discovery before calling this api, otherwise the callback
+ * may fail to return the desired device.</p>
+ *
* <p>Calling this API requires a uses-feature
* {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
**
@@ -377,6 +382,7 @@ public final class CompanionDeviceManager {
* @see AssociationRequest.Builder
* @see #getMyAssociations()
* @see #disassociate(int)
+ * @see BluetoothAdapter#cancelDiscovery()
*/
@UserHandleAware
@RequiresPermission(anyOf = {
@@ -403,6 +409,34 @@ public final class CompanionDeviceManager {
}
/**
+ * Cancel the current association activity.
+ *
+ * <p>The app should launch the returned {@code intentSender} by calling
+ * {@link Activity#startIntentSenderForResult(IntentSender, int, Intent, int, int, int)} to
+ * cancel the current association activity</p>
+ *
+ * <p>Calling this API requires a uses-feature
+ * {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
+ *
+ * @return An {@link IntentSender} that the app should use to launch in order to cancel the
+ * current association activity
+ */
+ @UserHandleAware
+ @Nullable
+ public IntentSender buildAssociationCancellationIntent() {
+ if (!checkFeaturePresent()) return null;
+
+ try {
+ PendingIntent pendingIntent = mService.buildAssociationCancellationIntent(
+ mContext.getOpPackageName(), mContext.getUserId());
+ return pendingIntent.getIntentSender();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+
+ /**
* <p>Calling this API requires a uses-feature
* {@link PackageManager#FEATURE_COMPANION_DEVICE_SETUP} declaration in the manifest</p>
*
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 17e313252010..24ef52b37dab 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -82,4 +82,6 @@ interface ICompanionDeviceManager {
void detachSystemDataTransport(String packageName, int userId, int associationId);
boolean isCompanionApplicationBound(String packageName, int userId);
+
+ PendingIntent buildAssociationCancellationIntent(in String callingPackage, int userId);
}
diff --git a/core/java/android/companion/OWNERS b/core/java/android/companion/OWNERS
index 004f66caed7b..0348fe2776fe 100644
--- a/core/java/android/companion/OWNERS
+++ b/core/java/android/companion/OWNERS
@@ -1,5 +1,3 @@
-ewol@google.com
evanxinchen@google.com
guojing@google.com
-svetoslavganov@google.com
-sergeynv@google.com \ No newline at end of file
+raphk@google.com \ No newline at end of file
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 0d73c1375b03..cb5a99fcc811 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -52,6 +52,7 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PermissionMethod;
+import android.content.pm.PermissionName;
import android.content.res.AssetManager;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
@@ -6088,7 +6089,8 @@ public abstract class Context {
@CheckResult(suggest="#enforcePermission(String,int,int,String)")
@PackageManager.PermissionResult
@PermissionMethod
- public abstract int checkPermission(@NonNull String permission, int pid, int uid);
+ public abstract int checkPermission(
+ @NonNull @PermissionName String permission, int pid, int uid);
/** @hide */
@SuppressWarnings("HiddenAbstractMethod")
@@ -6121,7 +6123,7 @@ public abstract class Context {
@CheckResult(suggest="#enforceCallingPermission(String,String)")
@PackageManager.PermissionResult
@PermissionMethod
- public abstract int checkCallingPermission(@NonNull String permission);
+ public abstract int checkCallingPermission(@NonNull @PermissionName String permission);
/**
* Determine whether the calling process of an IPC <em>or you</em> have been
@@ -6142,7 +6144,7 @@ public abstract class Context {
@CheckResult(suggest="#enforceCallingOrSelfPermission(String,String)")
@PackageManager.PermissionResult
@PermissionMethod
- public abstract int checkCallingOrSelfPermission(@NonNull String permission);
+ public abstract int checkCallingOrSelfPermission(@NonNull @PermissionName String permission);
/**
* Determine whether <em>you</em> have been granted a particular permission.
@@ -6172,7 +6174,7 @@ public abstract class Context {
*/
@PermissionMethod
public abstract void enforcePermission(
- @NonNull String permission, int pid, int uid, @Nullable String message);
+ @NonNull @PermissionName String permission, int pid, int uid, @Nullable String message);
/**
* If the calling process of an IPC you are handling has not been
@@ -6194,7 +6196,7 @@ public abstract class Context {
*/
@PermissionMethod
public abstract void enforceCallingPermission(
- @NonNull String permission, @Nullable String message);
+ @NonNull @PermissionName String permission, @Nullable String message);
/**
* If neither you nor the calling process of an IPC you are
@@ -6211,7 +6213,7 @@ public abstract class Context {
*/
@PermissionMethod
public abstract void enforceCallingOrSelfPermission(
- @NonNull String permission, @Nullable String message);
+ @NonNull @PermissionName String permission, @Nullable String message);
/**
* Grant permission to access a specific Uri to another package, regardless
diff --git a/core/java/android/content/pm/PermissionMethod.java b/core/java/android/content/pm/PermissionMethod.java
index 021b2e1cd8f1..ba97342c5e3e 100644
--- a/core/java/android/content/pm/PermissionMethod.java
+++ b/core/java/android/content/pm/PermissionMethod.java
@@ -26,7 +26,7 @@ import java.lang.annotation.Target;
* Documents that the subject method's job is to look
* up whether the provided or calling uid/pid has the requested permission.
*
- * Methods should either return `void`, but potentially throw {@link SecurityException},
+ * <p>Methods should either return `void`, but potentially throw {@link SecurityException},
* or return {@link android.content.pm.PackageManager.PermissionResult} `int`.
*
* @hide
diff --git a/core/java/android/content/pm/PermissionName.java b/core/java/android/content/pm/PermissionName.java
new file mode 100644
index 000000000000..719e13be05cc
--- /dev/null
+++ b/core/java/android/content/pm/PermissionName.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.LOCAL_VARIABLE;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.PARAMETER;
+import static java.lang.annotation.RetentionPolicy.CLASS;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Denotes that the annotated {@link String} represents a permission name.
+ *
+ * @hide
+ */
+@Retention(CLASS)
+@Target({PARAMETER, METHOD, LOCAL_VARIABLE, FIELD})
+public @interface PermissionName {}
diff --git a/core/java/android/os/Trace.java b/core/java/android/os/Trace.java
index 4965057a7fdb..8bfa0e99e3b4 100644
--- a/core/java/android/os/Trace.java
+++ b/core/java/android/os/Trace.java
@@ -340,9 +340,6 @@ public final class Trace {
* @hide
*/
public static void instant(long traceTag, String methodName) {
- if (methodName == null) {
- throw new IllegalArgumentException("methodName cannot be null");
- }
if (isTagEnabled(traceTag)) {
nativeInstant(traceTag, methodName);
}
@@ -357,12 +354,6 @@ public final class Trace {
* @hide
*/
public static void instantForTrack(long traceTag, String trackName, String methodName) {
- if (trackName == null) {
- throw new IllegalArgumentException("trackName cannot be null");
- }
- if (methodName == null) {
- throw new IllegalArgumentException("methodName cannot be null");
- }
if (isTagEnabled(traceTag)) {
nativeInstantForTrack(traceTag, trackName, methodName);
}
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 345486e390cd..99b9156dacde 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -808,6 +808,13 @@ public final class DeviceConfig {
@SystemApi
public static final String NAMESPACE_BACKUP_AND_RESTORE = "backup_and_restore";
+ /**
+ * Namespace for ARC App Compat related features.
+ *
+ * @hide
+ */
+ public static final String NAMESPACE_ARC_APP_COMPAT = "arc_app_compat";
+
private static final Object sLock = new Object();
@GuardedBy("sLock")
private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners =
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 8efc5eb6b6ff..e720f1ab1523 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -65,6 +65,7 @@ public final class KeymasterDefs {
public static final int KM_TAG_PADDING = Tag.PADDING; // KM_ENUM_REP | 6;
public static final int KM_TAG_CALLER_NONCE = Tag.CALLER_NONCE; // KM_BOOL | 7;
public static final int KM_TAG_MIN_MAC_LENGTH = Tag.MIN_MAC_LENGTH; // KM_UINT | 8;
+ public static final int KM_TAG_EC_CURVE = Tag.EC_CURVE; // KM_ENUM | 10;
public static final int KM_TAG_RSA_PUBLIC_EXPONENT = Tag.RSA_PUBLIC_EXPONENT; // KM_ULONG | 200;
public static final int KM_TAG_INCLUDE_UNIQUE_ID = Tag.INCLUDE_UNIQUE_ID; // KM_BOOL | 202;
diff --git a/core/java/android/text/GraphemeClusterSegmentIterator.java b/core/java/android/text/GraphemeClusterSegmentFinder.java
index e3976a7eab35..8b3db0a51691 100644
--- a/core/java/android/text/GraphemeClusterSegmentIterator.java
+++ b/core/java/android/text/GraphemeClusterSegmentFinder.java
@@ -21,16 +21,20 @@ import android.annotation.NonNull;
import android.graphics.Paint;
/**
- * Implementation of {@code SegmentIterator} using grapheme clusters as the text segment. Whitespace
+ * Implementation of {@code SegmentFinder} using grapheme clusters as the text segment. Whitespace
* characters are included as segments.
*
- * @hide
+ * <p>For example, the text "a pot" would be divided into five text segments: "a", " ", "p", "o",
+ * "t".
+ *
+ * @see <a href="https://unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries">Unicode Text
+ * Segmentation - Grapheme Cluster Boundaries</a>
*/
-public class GraphemeClusterSegmentIterator extends SegmentIterator {
+public class GraphemeClusterSegmentFinder extends SegmentFinder {
private final CharSequence mText;
private final TextPaint mTextPaint;
- public GraphemeClusterSegmentIterator(
+ public GraphemeClusterSegmentFinder(
@NonNull CharSequence text, @NonNull TextPaint textPaint) {
mText = text;
mTextPaint = textPaint;
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index dbb41f47a495..913e9cc1a246 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -168,6 +168,31 @@ public abstract class Layout {
public static final float DEFAULT_LINESPACING_ADDITION = 0.0f;
/**
+ * Strategy which considers a text segment to be inside a rectangle area if the segment bounds
+ * intersect the rectangle.
+ */
+ @NonNull
+ public static final TextInclusionStrategy INCLUSION_STRATEGY_ANY_OVERLAP =
+ RectF::intersects;
+
+ /**
+ * Strategy which considers a text segment to be inside a rectangle area if the center of the
+ * segment bounds is inside the rectangle.
+ */
+ @NonNull
+ public static final TextInclusionStrategy INCLUSION_STRATEGY_CONTAINS_CENTER =
+ (segmentBounds, area) ->
+ area.contains(segmentBounds.centerX(), segmentBounds.centerY());
+
+ /**
+ * Strategy which considers a text segment to be inside a rectangle area if the segment bounds
+ * are completely contained within the rectangle.
+ */
+ @NonNull
+ public static final TextInclusionStrategy INCLUSION_STRATEGY_CONTAINS_ALL =
+ (segmentBounds, area) -> area.contains(segmentBounds);
+
+ /**
* Return how wide a layout must be in order to display the specified text with one line per
* paragraph.
*
@@ -1818,11 +1843,11 @@ public abstract class Layout {
* is the start of the first text segment inside the area, and the end of the range is the end
* of the last text segment inside the area.
*
- * <p>A text segment is considered to be inside the area if the center of its bounds is inside
- * the area. If a text segment spans multiple lines or multiple directional runs (e.g. a
- * hyphenated word), the text segment is divided into pieces at the line and run breaks, then
- * the text segment is considered to be inside the area if any of its pieces have their center
- * inside the area.
+ * <p>A text segment is considered to be inside the area according to the provided {@link
+ * TextInclusionStrategy}. If a text segment spans multiple lines or multiple directional runs
+ * (e.g. a hyphenated word), the text segment is divided into pieces at the line and run breaks,
+ * then the text segment is considered to be inside the area if any of its pieces are inside the
+ * area.
*
* <p>The returned range may also include text segments which are not inside the specified area,
* if those text segments are in between text segments which are inside the area. For example,
@@ -1830,62 +1855,59 @@ public abstract class Layout {
* inside the area and "segment2" is not.
*
* @param area area for which the text range will be found
- * @param segmentIterator iterator for determining the ranges of text to be considered as a text
- * segment
+ * @param segmentFinder SegmentFinder for determining the ranges of text to be considered as a
+ * text segment
+ * @param inclusionStrategy strategy for determining whether a text segment is inside the
+ * specified area
* @return int array of size 2 containing the start (inclusive) and end (exclusive) character
* offsets of the range, or null if there are no text segments inside the area
- * @hide
*/
@Nullable
- public int[] getRangeForRect(@NonNull RectF area, @NonNull SegmentIterator segmentIterator) {
- // Find the first line whose vertical center is below the top of the area.
+ public int[] getRangeForRect(@NonNull RectF area, @NonNull SegmentFinder segmentFinder,
+ @NonNull TextInclusionStrategy inclusionStrategy) {
+ // Find the first line whose bottom (without line spacing) is below the top of the area.
int startLine = getLineForVertical((int) area.top);
- int startLineTop = getLineTop(startLine);
- int startLineBottom = getLineBottom(startLine, /* includeLineSpacing= */ false);
- if (area.top > (startLineTop + startLineBottom) / 2f) {
+ if (area.top > getLineBottom(startLine, /* includeLineSpacing= */ false)) {
startLine++;
if (startLine >= getLineCount()) {
- // The top of the area is below the vertical center of the last line, so the area
- // does not contain any text.
+ // The entire area is below the last line, so it does not contain any text.
return null;
}
}
- // Find the last line whose vertical center is above the bottom of the area.
+ // Find the last line whose top is above the bottom of the area.
int endLine = getLineForVertical((int) area.bottom);
- int endLineTop = getLineTop(endLine);
- int endLineBottom = getLineBottom(endLine, /* includeLineSpacing= */ false);
- if (area.bottom < (endLineTop + endLineBottom) / 2f) {
- endLine--;
+ if (endLine == 0 && area.bottom < getLineTop(0)) {
+ // The entire area is above the first line, so it does not contain any text.
+ return null;
}
if (endLine < startLine) {
- // There are no lines with vertical centers between the top and bottom of the area, so
- // the area does not contain any text.
+ // The entire area is between two lines, so it does not contain any text.
return null;
}
- int start = getStartOrEndOffsetForHorizontalInterval(
- startLine, area.left, area.right, segmentIterator, /* getStart= */ true);
+ int start = getStartOrEndOffsetForAreaWithinLine(
+ startLine, area, segmentFinder, inclusionStrategy, /* getStart= */ true);
// If the area does not contain any text on this line, keep trying subsequent lines until
// the end line is reached.
while (start == -1 && startLine < endLine) {
startLine++;
- start = getStartOrEndOffsetForHorizontalInterval(
- startLine, area.left, area.right, segmentIterator, /* getStart= */ true);
+ start = getStartOrEndOffsetForAreaWithinLine(
+ startLine, area, segmentFinder, inclusionStrategy, /* getStart= */ true);
}
if (start == -1) {
// All lines were checked, the area does not contain any text.
return null;
}
- int end = getStartOrEndOffsetForHorizontalInterval(
- endLine, area.left, area.right, segmentIterator, /* getStart= */ false);
+ int end = getStartOrEndOffsetForAreaWithinLine(
+ endLine, area, segmentFinder, inclusionStrategy, /* getStart= */ false);
// If the area does not contain any text on this line, keep trying previous lines until
// the start line is reached.
while (end == -1 && startLine < endLine) {
endLine--;
- end = getStartOrEndOffsetForHorizontalInterval(
- endLine, area.left, area.right, segmentIterator, /* getStart= */ false);
+ end = getStartOrEndOffsetForAreaWithinLine(
+ endLine, area, segmentFinder, inclusionStrategy, /* getStart= */ false);
}
if (end == -1) {
// All lines were checked, the area does not contain any text.
@@ -1893,33 +1915,39 @@ public abstract class Layout {
}
// If a text segment spans multiple lines or multiple directional runs (e.g. a hyphenated
- // word), then getStartOrEndOffsetForHorizontalInterval() can return an offset in the middle
- // of a text segment. Adjust the range to include the rest of any partial text segments. If
+ // word), then getStartOrEndOffsetForAreaWithinLine() can return an offset in the middle of
+ // a text segment. Adjust the range to include the rest of any partial text segments. If
// start is already the start boundary of a text segment, then this is a no-op.
- start = segmentIterator.previousStartBoundary(start + 1);
- end = segmentIterator.nextEndBoundary(end - 1);
+ start = segmentFinder.previousStartBoundary(start + 1);
+ end = segmentFinder.nextEndBoundary(end - 1);
return new int[] {start, end};
}
/**
- * Finds the start character offset of the first text segment inside a horizontal interval
- * within a line, or the end character offset of the last text segment inside the horizontal
- * interval.
+ * Finds the start character offset of the first text segment within a line inside the specified
+ * rectangle area, or the end character offset of the last text segment inside the area.
*
* @param line index of the line to search
- * @param left left bound of the horizontal interval
- * @param right right bound of the horizontal interval
- * @param segmentIterator iterator for determining the ranges of text to be considered as a text
- * segment
- * @param getStart true to find the start of the first text segment inside the horizontal
- * interval, false to find the end of the last text segment
- * @return the start character offset of the first text segment inside the horizontal interval,
- * or the end character offset of the last text segment inside the horizontal interval.
- */
- private int getStartOrEndOffsetForHorizontalInterval(
- @IntRange(from = 0) int line, float left, float right,
- @NonNull SegmentIterator segmentIterator, boolean getStart) {
+ * @param area area inside which text segments will be found
+ * @param segmentFinder SegmentFinder for determining the ranges of text to be considered as a
+ * text segment
+ * @param inclusionStrategy strategy for determining whether a text segment is inside the
+ * specified area
+ * @param getStart true to find the start of the first text segment inside the area, false to
+ * find the end of the last text segment
+ * @return the start character offset of the first text segment inside the area, or the end
+ * character offset of the last text segment inside the area.
+ */
+ private int getStartOrEndOffsetForAreaWithinLine(
+ @IntRange(from = 0) int line,
+ @NonNull RectF area,
+ @NonNull SegmentFinder segmentFinder,
+ @NonNull TextInclusionStrategy inclusionStrategy,
+ boolean getStart) {
+ int lineTop = getLineTop(line);
+ int lineBottom = getLineBottom(line, /* includeLineSpacing= */ false);
+
int lineStartOffset = getLineStart(line);
int lineEndOffset = getLineEnd(line);
if (lineStartOffset == lineEndOffset) {
@@ -1952,14 +1980,16 @@ public abstract class Layout {
int result =
getStart
- ? getStartOffsetForHorizontalIntervalWithinRun(
- left, right, lineStartOffset, lineStartPos, horizontalBounds,
- runStartOffset, runEndOffset, runLeft, runRight, isRtl,
- segmentIterator)
- : getEndOffsetForHorizontalIntervalWithinRun(
- left, right, lineStartOffset, lineStartPos, horizontalBounds,
+ ? getStartOffsetForAreaWithinRun(
+ area, lineTop, lineBottom,
+ lineStartOffset, lineStartPos, horizontalBounds,
+ runStartOffset, runEndOffset, runLeft, runRight, isRtl,
+ segmentFinder, inclusionStrategy)
+ : getEndOffsetForAreaWithinRun(
+ area, lineTop, lineBottom,
+ lineStartOffset, lineStartPos, horizontalBounds,
runStartOffset, runEndOffset, runLeft, runRight, isRtl,
- segmentIterator);
+ segmentFinder, inclusionStrategy);
if (result >= 0) {
return result;
}
@@ -1970,11 +2000,12 @@ public abstract class Layout {
}
/**
- * Finds the start character offset of the first text segment inside a horizontal interval
- * within a directional run.
+ * Finds the start character offset of the first text segment within a directional run inside
+ * the specified rectangle area.
*
- * @param left left bound of the horizontal interval
- * @param right right bound of the horizontal interval
+ * @param area area inside which text segments will be found
+ * @param lineTop top of the line containing this run
+ * @param lineBottom bottom (not including line spacing) of the line containing this run
* @param lineStartOffset start character offset of the line containing this run
* @param lineStartPos start position of the line containing this run
* @param horizontalBounds array containing the signed horizontal bounds of the characters in
@@ -1985,28 +2016,32 @@ public abstract class Layout {
* @param runLeft left bound of the run
* @param runRight right bound of the run
* @param isRtl whether the run is right-to-left
- * @param segmentIterator iterator for determining the ranges of text to be considered as a text
- * segment
- * @return the start character offset of the first text segment inside the horizontal interval
- */
- private static int getStartOffsetForHorizontalIntervalWithinRun(
- float left, float right,
+ * @param segmentFinder SegmentFinder for determining the ranges of text to be considered as a
+ * text segment
+ * @param inclusionStrategy strategy for determining whether a text segment is inside the
+ * specified area
+ * @return the start character offset of the first text segment inside the area
+ */
+ private static int getStartOffsetForAreaWithinRun(
+ @NonNull RectF area,
+ int lineTop, int lineBottom,
@IntRange(from = 0) int lineStartOffset,
@IntRange(from = 0) int lineStartPos,
@NonNull float[] horizontalBounds,
@IntRange(from = 0) int runStartOffset, @IntRange(from = 0) int runEndOffset,
float runLeft, float runRight,
boolean isRtl,
- @NonNull SegmentIterator segmentIterator) {
- if (runRight < left || runLeft > right) {
- // The run does not overlap the interval.
+ @NonNull SegmentFinder segmentFinder,
+ @NonNull TextInclusionStrategy inclusionStrategy) {
+ if (runRight < area.left || runLeft > area.right) {
+ // The run does not overlap the area.
return -1;
}
- // Find the first character in the run whose bounds overlap with the interval.
+ // Find the first character in the run whose bounds overlap with the area.
// firstCharOffset is an offset index within the line.
int firstCharOffset;
- if ((!isRtl && left <= runLeft) || (isRtl && right >= runRight)) {
+ if ((!isRtl && area.left <= runLeft) || (isRtl && area.right >= runRight)) {
firstCharOffset = runStartOffset;
} else {
int low = runStartOffset;
@@ -2016,73 +2051,78 @@ public abstract class Layout {
guess = (high + low) / 2;
// Left edge of the character at guess
float pos = lineStartPos + horizontalBounds[2 * guess];
- if ((!isRtl && pos > left) || (isRtl && pos < right)) {
+ if ((!isRtl && pos > area.left) || (isRtl && pos < area.right)) {
high = guess;
} else {
low = guess;
}
}
- // The interval bound is between the left edge of the character at low and the left edge
- // of the character at high. For LTR text, this is within the character at low. For RTL
+ // The area edge is between the left edge of the character at low and the left edge of
+ // the character at high. For LTR text, this is within the character at low. For RTL
// text, this is within the character at high.
firstCharOffset = isRtl ? high : low;
}
// Find the first text segment containing this character (or, if no text segment contains
// this character, the first text segment after this character). All previous text segments
- // in this run are to the left (for LTR) of the interval.
- segmentIterator.setRunLimits(
- lineStartOffset + runStartOffset, lineStartOffset + runEndOffset);
+ // in this run are to the left (for LTR) of the area.
int segmentEndOffset =
- segmentIterator.nextEndBoundaryOrRunEnd(lineStartOffset + firstCharOffset);
- if (segmentEndOffset == SegmentIterator.DONE) {
+ segmentFinder.nextEndBoundary(lineStartOffset + firstCharOffset);
+ if (segmentEndOffset == SegmentFinder.DONE) {
// There are no text segments containing or after firstCharOffset, so no text segments
- // in this run overlap the interval.
- return -1;
- }
- int segmentStartOffset = segmentIterator.previousStartBoundaryOrRunStart(segmentEndOffset);
- float segmentCenter = lineStartPos
- + (horizontalBounds[2 * (segmentStartOffset - lineStartOffset)]
- + horizontalBounds[2 * (segmentEndOffset - lineStartOffset) - 1]) / 2;
- if ((!isRtl && segmentCenter > right) || (isRtl && segmentCenter < left)) {
- // The entire interval is to the left (for LTR) of the text segment's center. So the
- // interval does not contain any text segments within this run.
+ // in this run overlap the area.
return -1;
}
- if ((!isRtl && segmentCenter >= left) || (isRtl && segmentCenter <= right)) {
- // The center is within the interval, so return the start offset of this text segment.
- return segmentStartOffset;
- }
-
- // If first text segment's center is not within the interval, try the next text segment.
- segmentStartOffset = segmentIterator.nextStartBoundaryWithinRunLimits(segmentStartOffset);
- if (segmentStartOffset == SegmentIterator.DONE
- || segmentStartOffset == lineStartOffset + runEndOffset) {
- // No more text segments within this run.
+ int segmentStartOffset = segmentFinder.previousStartBoundary(segmentEndOffset);
+ if (segmentStartOffset >= lineStartOffset + runEndOffset) {
+ // The text segment is after the end of this run, so no text segments in this run
+ // overlap the area.
return -1;
}
- segmentEndOffset = segmentIterator.nextEndBoundaryOrRunEnd(segmentStartOffset);
- segmentCenter = lineStartPos
- + (horizontalBounds[2 * (segmentStartOffset - lineStartOffset)]
- + horizontalBounds[2 * (segmentEndOffset - lineStartOffset) - 1]) / 2;
- // We already know that segmentCenter >= left (for LTR) since the previous word contains the
- // left point.
- if ((!isRtl && segmentCenter <= right) || (isRtl && segmentCenter >= left)) {
- return segmentStartOffset;
- }
-
- // If the second text segment is also not within the interval, then this means that the
- // interval is between the centers of the first and second text segments, so it does not
- // contain any text segments on this line.
- return -1;
- }
-
- /**
- * Finds the end character offset of the last text segment inside a horizontal interval within a
- * directional run.
+ // If the segment extends outside of this run, only consider the piece of the segment within
+ // this run.
+ segmentStartOffset = Math.max(segmentStartOffset, lineStartOffset + runStartOffset);
+ segmentEndOffset = Math.min(segmentEndOffset, lineStartOffset + runEndOffset);
+
+ RectF segmentBounds = new RectF(0, lineTop, 0, lineBottom);
+ while (true) {
+ // Start (left for LTR, right for RTL) edge of the character at segmentStartOffset.
+ float segmentStart = lineStartPos + horizontalBounds[
+ 2 * (segmentStartOffset - lineStartOffset) + (isRtl ? 1 : 0)];
+ if ((!isRtl && segmentStart > area.right) || (isRtl && segmentStart < area.left)) {
+ // The entire area is to the left (for LTR) of the text segment. So the area does
+ // not contain any text segments within this run.
+ return -1;
+ }
+ // End (right for LTR, left for RTL) edge of the character at (segmentStartOffset - 1).
+ float segmentEnd = lineStartPos + horizontalBounds[
+ 2 * (segmentEndOffset - lineStartOffset - 1) + (isRtl ? 0 : 1)];
+ segmentBounds.left = isRtl ? segmentEnd : segmentStart;
+ segmentBounds.right = isRtl ? segmentStart : segmentEnd;
+ if (inclusionStrategy.isSegmentInside(segmentBounds, area)) {
+ return segmentStartOffset;
+ }
+ // Try the next text segment.
+ segmentStartOffset = segmentFinder.nextStartBoundary(segmentStartOffset);
+ if (segmentStartOffset == SegmentFinder.DONE
+ || segmentStartOffset >= lineStartOffset + runEndOffset) {
+ // No more text segments within this run.
+ return -1;
+ }
+ segmentEndOffset = segmentFinder.nextEndBoundary(segmentStartOffset);
+ // If the segment extends past the end of this run, only consider the piece of the
+ // segment within this run.
+ segmentEndOffset = Math.min(segmentEndOffset, lineStartOffset + runEndOffset);
+ }
+ }
+
+ /**
+ * Finds the end character offset of the last text segment within a directional run inside the
+ * specified rectangle area.
*
- * @param left left bound of the horizontal interval
- * @param right right bound of the horizontal interval
+ * @param area area inside which text segments will be found
+ * @param lineTop top of the line containing this run
+ * @param lineBottom bottom (not including line spacing) of the line containing this run
* @param lineStartOffset start character offset of the line containing this run
* @param lineStartPos start position of the line containing this run
* @param horizontalBounds array containing the signed horizontal bounds of the characters in
@@ -2093,28 +2133,32 @@ public abstract class Layout {
* @param runLeft left bound of the run
* @param runRight right bound of the run
* @param isRtl whether the run is right-to-left
- * @param segmentIterator iterator for determining the ranges of text to be considered as a text
- * segment
- * @return the end character offset of the last text segment inside the horizontal interval
- */
- private static int getEndOffsetForHorizontalIntervalWithinRun(
- float left, float right,
+ * @param segmentFinder SegmentFinder for determining the ranges of text to be considered as a
+ * text segment
+ * @param inclusionStrategy strategy for determining whether a text segment is inside the
+ * specified area
+ * @return the end character offset of the last text segment inside the area
+ */
+ private static int getEndOffsetForAreaWithinRun(
+ @NonNull RectF area,
+ int lineTop, int lineBottom,
@IntRange(from = 0) int lineStartOffset,
@IntRange(from = 0) int lineStartPos,
@NonNull float[] horizontalBounds,
@IntRange(from = 0) int runStartOffset, @IntRange(from = 0) int runEndOffset,
float runLeft, float runRight,
boolean isRtl,
- @NonNull SegmentIterator segmentIterator) {
- if (runRight < left || runLeft > right) {
- // The run does not overlap the interval.
+ @NonNull SegmentFinder segmentFinder,
+ @NonNull TextInclusionStrategy inclusionStrategy) {
+ if (runRight < area.left || runLeft > area.right) {
+ // The run does not overlap the area.
return -1;
}
- // Find the last character in the run whose bounds overlap with the interval.
+ // Find the last character in the run whose bounds overlap with the area.
// firstCharOffset is an offset index within the line.
int lastCharOffset;
- if ((!isRtl && right >= runRight) || (isRtl && left <= runLeft)) {
+ if ((!isRtl && area.right >= runRight) || (isRtl && area.left <= runLeft)) {
lastCharOffset = runEndOffset - 1;
} else {
int low = runStartOffset;
@@ -2124,67 +2168,70 @@ public abstract class Layout {
guess = (high + low) / 2;
// Left edge of the character at guess
float pos = lineStartPos + horizontalBounds[2 * guess];
- if ((!isRtl && pos > right) || (isRtl && pos < left)) {
+ if ((!isRtl && pos > area.right) || (isRtl && pos < area.left)) {
high = guess;
} else {
low = guess;
}
}
- // The interval bound is between the left edge of the character at low and the left edge
- // of the character at high. For LTR text, this is within the character at low. For RTL
+ // The area edge is between the left edge of the character at low and the left edge of
+ // the character at high. For LTR text, this is within the character at low. For RTL
// text, this is within the character at high.
lastCharOffset = isRtl ? high : low;
}
- // Find the last text segment containing this character (or, if no text segment
- // contains this character, the first text segment before this character). All
- // following text segments in this run are to the right (for LTR) of the interval.
- segmentIterator.setRunLimits(
- lineStartOffset + runStartOffset, lineStartOffset + runEndOffset);
+ // Find the last text segment containing this character (or, if no text segment contains
+ // this character, the first text segment before this character). All following text
+ // segments in this run are to the right (for LTR) of the area.
// + 1 to allow segmentStartOffset = lineStartOffset + lastCharOffset
int segmentStartOffset =
- segmentIterator.previousStartBoundaryOrRunStart(
- lineStartOffset + lastCharOffset + 1);
- if (segmentStartOffset == SegmentIterator.DONE) {
+ segmentFinder.previousStartBoundary(lineStartOffset + lastCharOffset + 1);
+ if (segmentStartOffset == SegmentFinder.DONE) {
// There are no text segments containing or before lastCharOffset, so no text segments
- // in this run overlap the interval.
+ // in this run overlap the area.
return -1;
}
- int segmentEndOffset = segmentIterator.nextEndBoundaryOrRunEnd(segmentStartOffset);
- float segmentCenter = lineStartPos
- + (horizontalBounds[2 * (segmentStartOffset - lineStartOffset)]
- + horizontalBounds[2 * (segmentEndOffset - lineStartOffset) - 1]) / 2;
- if ((!isRtl && segmentCenter < left) || (isRtl && segmentCenter > right)) {
- // The entire interval is to the right (for LTR) of the text segment's center. So the
- // interval does not contain any text segments within this run.
+ int segmentEndOffset = segmentFinder.nextEndBoundary(segmentStartOffset);
+ if (segmentEndOffset <= lineStartOffset + runStartOffset) {
+ // The text segment is before the start of this run, so no text segments in this run
+ // overlap the area.
return -1;
}
- if ((!isRtl && segmentCenter <= right) || (isRtl && segmentCenter >= left)) {
- // The center is within the interval, so return the end offset of this text segment.
- return segmentEndOffset;
- }
+ // If the segment extends outside of this run, only consider the piece of the segment within
+ // this run.
+ segmentStartOffset = Math.max(segmentStartOffset, lineStartOffset + runStartOffset);
+ segmentEndOffset = Math.min(segmentEndOffset, lineStartOffset + runEndOffset);
- // If first text segment's center is not within the interval, try the next text segment.
- segmentEndOffset = segmentIterator.previousEndBoundaryWithinRunLimits(segmentEndOffset);
- if (segmentEndOffset == SegmentIterator.DONE
- || segmentEndOffset == lineStartOffset + runStartOffset) {
- // No more text segments within this run.
- return -1;
- }
- segmentStartOffset = segmentIterator.previousStartBoundaryOrRunStart(segmentEndOffset);
- segmentCenter = lineStartPos
- + (horizontalBounds[2 * (segmentStartOffset - lineStartOffset)]
- + horizontalBounds[2 * (segmentEndOffset - lineStartOffset) - 1]) / 2;
- // We already know that segmentCenter <= right (for LTR) since the following word
- // contains the right point.
- if ((!isRtl && segmentCenter >= left) || (isRtl && segmentCenter <= right)) {
- return segmentEndOffset;
+ RectF segmentBounds = new RectF(0, lineTop, 0, lineBottom);
+ while (true) {
+ // End (right for LTR, left for RTL) edge of the character at (segmentStartOffset - 1).
+ float segmentEnd = lineStartPos + horizontalBounds[
+ 2 * (segmentEndOffset - lineStartOffset - 1) + (isRtl ? 0 : 1)];
+ if ((!isRtl && segmentEnd < area.left) || (isRtl && segmentEnd > area.right)) {
+ // The entire area is to the right (for LTR) of the text segment. So the
+ // area does not contain any text segments within this run.
+ return -1;
+ }
+ // Start (left for LTR, right for RTL) edge of the character at segmentStartOffset.
+ float segmentStart = lineStartPos + horizontalBounds[
+ 2 * (segmentStartOffset - lineStartOffset) + (isRtl ? 1 : 0)];
+ segmentBounds.left = isRtl ? segmentEnd : segmentStart;
+ segmentBounds.right = isRtl ? segmentStart : segmentEnd;
+ if (inclusionStrategy.isSegmentInside(segmentBounds, area)) {
+ return segmentEndOffset;
+ }
+ // Try the previous text segment.
+ segmentEndOffset = segmentFinder.previousEndBoundary(segmentEndOffset);
+ if (segmentEndOffset == SegmentFinder.DONE
+ || segmentEndOffset <= lineStartOffset + runStartOffset) {
+ // No more text segments within this run.
+ return -1;
+ }
+ segmentStartOffset = segmentFinder.previousStartBoundary(segmentEndOffset);
+ // If the segment extends past the start of this run, only consider the piece of the
+ // segment within this run.
+ segmentStartOffset = Math.max(segmentStartOffset, lineStartOffset + runStartOffset);
}
-
- // If the second text segment is also not within the interval, then this means that the
- // interval is between the centers of the first and second text segments, so it does not
- // contain any text segments on this line.
- return -1;
}
/**
@@ -3158,4 +3205,22 @@ public abstract class Layout {
@TextSelectionLayout int textSelectionLayout);
}
+ /**
+ * Strategy for determining whether a text segment is inside a rectangle area.
+ *
+ * @see #getRangeForRect(RectF, SegmentFinder, TextInclusionStrategy)
+ */
+ @FunctionalInterface
+ public interface TextInclusionStrategy {
+ /**
+ * Returns true if this {@link TextInclusionStrategy} considers the segment with bounds
+ * {@code segmentBounds} to be inside {@code area}.
+ *
+ * <p>The segment is a range of text which does not cross line boundaries or directional run
+ * boundaries. The horizontal bounds of the segment are the start bound of the first
+ * character to the end bound of the last character. The vertical bounds match the line
+ * bounds ({@code getLineTop(line)} and {@code getLineBottom(line, false)}).
+ */
+ boolean isSegmentInside(@NonNull RectF segmentBounds, @NonNull RectF area);
+ }
}
diff --git a/core/java/android/text/SegmentIterator.java b/core/java/android/text/SegmentFinder.java
index 00522e542eec..d34365dbef22 100644
--- a/core/java/android/text/SegmentIterator.java
+++ b/core/java/android/text/SegmentFinder.java
@@ -17,26 +17,24 @@
package android.text;
import android.annotation.IntRange;
+import android.graphics.RectF;
/**
* Finds text segment boundaries within text. Subclasses can implement different types of text
- * segments. Grapheme clusters and words are examples of possible text segments.
+ * segments. Grapheme clusters and words are examples of possible text segments. These are
+ * implemented by {@link GraphemeClusterSegmentFinder} and {@link WordSegmentFinder}.
*
- * <p>Granular units may not overlap, so every character belongs to at most one text segment. A
+ * <p>Text segments may not overlap, so every character belongs to at most one text segment. A
* character may belong to no text segments.
*
- * <p>For example, a word level text segment iterator may subdivide the text "Hello, World!" into
- * four text segments: "Hello", ",", "World", "!". The space character does not belong to any text
- * segments.
+ * <p>For example, WordSegmentFinder subdivides the text "Hello, World!" into four text segments:
+ * "Hello", ",", "World", "!". The space character does not belong to any text segments.
*
- * @hide
+ * @see Layout#getRangeForRect(RectF, SegmentFinder, Layout.TextInclusionStrategy)
*/
-public abstract class SegmentIterator {
+public abstract class SegmentFinder {
public static final int DONE = -1;
- private int mRunStartOffset;
- private int mRunEndOffset;
-
/**
* Returns the character offset of the previous text segment start boundary before the specified
* character offset, or {@code DONE} if there are none.
@@ -60,52 +58,4 @@ public abstract class SegmentIterator {
* character offset, or {@code DONE} if there are none.
*/
public abstract int nextEndBoundary(@IntRange(from = 0) int offset);
-
- /**
- * Sets the start and end of a run which can be used to constrain the scope of the iterator's
- * search.
- *
- * @hide
- */
- void setRunLimits(
- @IntRange(from = 0) int runStartOffset, @IntRange(from = 0) int runEndOffset) {
- mRunStartOffset = runStartOffset;
- mRunEndOffset = runEndOffset;
- }
-
- /** @hide */
- int previousStartBoundaryOrRunStart(@IntRange(from = 0) int offset) {
- int start = previousStartBoundary(offset);
- if (start == DONE) {
- return DONE;
- }
- return Math.max(start, mRunStartOffset);
- }
-
- /** @hide */
- int previousEndBoundaryWithinRunLimits(@IntRange(from = 0) int offset) {
- int end = previousEndBoundary(offset);
- if (end <= mRunStartOffset) {
- return DONE;
- }
- return end;
- }
-
- /** @hide */
- int nextStartBoundaryWithinRunLimits(@IntRange(from = 0) int offset) {
- int start = nextStartBoundary(offset);
- if (start >= mRunEndOffset) {
- return DONE;
- }
- return start;
- }
-
- /** @hide */
- int nextEndBoundaryOrRunEnd(@IntRange(from = 0) int offset) {
- int end = nextEndBoundary(offset);
- if (end == DONE) {
- return DONE;
- }
- return Math.min(end, mRunEndOffset);
- }
}
diff --git a/core/java/android/text/WordSegmentIterator.java b/core/java/android/text/WordSegmentFinder.java
index 11153192b286..bf31e4cb1706 100644
--- a/core/java/android/text/WordSegmentIterator.java
+++ b/core/java/android/text/WordSegmentFinder.java
@@ -18,21 +18,36 @@ package android.text;
import android.annotation.IntRange;
import android.annotation.NonNull;
+import android.annotation.SuppressLint;
import android.icu.text.BreakIterator;
import android.text.method.WordIterator;
+import java.util.Locale;
+
/**
- * Implementation of {@code SegmentIterator} using words as the text segment. Word boundaries are
- * found using {@code WordIterator}. Whitespace characters are excluded, so they are not included in
+ * Implementation of {@link SegmentFinder} using words as the text segment. Word boundaries are
+ * found using {@link WordIterator}. Whitespace characters are excluded, so they are not included in
* any text segments.
*
- * @hide
+ * <p>For example, the text "Hello, World!" would be subdivided into four text segments: "Hello",
+ * ",", "World", "!". The space character does not belong to any text segments.
+ *
+ * @see <a href="https://unicode.org/reports/tr29/#Word_Boundaries">Unicode Text Segmentation - Word
+ * Boundaries</a>
*/
-public class WordSegmentIterator extends SegmentIterator {
+public class WordSegmentFinder extends SegmentFinder {
private final CharSequence mText;
private final WordIterator mWordIterator;
- public WordSegmentIterator(@NonNull CharSequence text, @NonNull WordIterator wordIterator) {
+ public WordSegmentFinder(
+ @NonNull CharSequence text, @SuppressLint("UseIcu") @NonNull Locale locale) {
+ mText = text;
+ mWordIterator = new WordIterator(locale);
+ mWordIterator.setCharSequence(text, 0, text.length());
+ }
+
+ /** @hide */
+ public WordSegmentFinder(@NonNull CharSequence text, @NonNull WordIterator wordIterator) {
mText = text;
mWordIterator = wordIterator;
}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 5b760a41aabd..c1fe6866fb4d 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -549,7 +549,10 @@ public final class InputMethodManager {
*/
@Deprecated
@GuardedBy("mH")
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 236937383,
+ maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE,
+ publicAlternatives = "Apps should not change behavior based on the currently connected"
+ + " IME. If absolutely needed, use {@link InputMethodInfo#getId()} instead.")
String mCurId;
/**
@@ -560,7 +563,9 @@ public final class InputMethodManager {
@Deprecated
@GuardedBy("mH")
@Nullable
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(trackingBug = 236937383,
+ maxTargetSdk = Build.VERSION_CODES.UPSIDE_DOWN_CAKE,
+ publicAlternatives = "Use methods on {@link InputMethodManager} instead.")
IInputMethodSession mCurMethod;
/**
@@ -718,14 +723,8 @@ public final class InputMethodManager {
ImeTracing.getInstance().triggerClientDump(
"InputMethodManager.DelegateImpl#startInput", InputMethodManager.this,
null /* icProto */);
- synchronized (mH) {
- mCurrentEditorInfo = null;
- mCompletions = null;
- mServedConnecting = true;
- }
- return startInputInner(startInputReason,
- focusedView != null ? focusedView.getWindowToken() : null, startInputFlags,
- softInputMode, windowFlags);
+ return startInputOnWindowFocusGainInternal(startInputReason, focusedView,
+ startInputFlags, softInputMode, windowFlags);
}
/**
@@ -800,7 +799,7 @@ public final class InputMethodManager {
// should be done in conjunction with telling the system service
// about the window gaining focus, to help make the transition
// smooth.
- if (startInput(StartInputReason.WINDOW_FOCUS_GAIN,
+ if (startInputOnWindowFocusGainInternal(StartInputReason.WINDOW_FOCUS_GAIN,
focusedView, startInputFlags, softInputMode, windowFlags)) {
return;
}
@@ -924,6 +923,19 @@ public final class InputMethodManager {
}
}
+ private boolean startInputOnWindowFocusGainInternal(@StartInputReason int startInputReason,
+ View focusedView, @StartInputFlags int startInputFlags,
+ @SoftInputModeFlags int softInputMode, int windowFlags) {
+ synchronized (mH) {
+ mCurrentEditorInfo = null;
+ mCompletions = null;
+ mServedConnecting = true;
+ }
+ return startInputInner(startInputReason,
+ focusedView != null ? focusedView.getWindowToken() : null, startInputFlags,
+ softInputMode, windowFlags);
+ }
+
@GuardedBy("mH")
private View getServedViewLocked() {
return mCurRootView != null ? mCurRootView.getImeFocusController().getServedViewLocked()
@@ -1136,7 +1148,7 @@ public final class InputMethodManager {
.checkFocus(mRestartOnNextWindowFocus, false)) {
final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS
: StartInputReason.DEACTIVATED_BY_IMMS;
- mDelegate.startInput(reason, null, 0, 0, 0);
+ startInputOnWindowFocusGainInternal(reason, null, 0, 0, 0);
}
}
}
@@ -2357,7 +2369,7 @@ public final class InputMethodManager {
// The view is running on a different thread than our own, so
// we need to reschedule our work for over there.
if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
- vh.post(() -> mDelegate.startInput(startInputReason, null, 0, 0, 0));
+ vh.post(() -> startInputOnWindowFocusGainInternal(startInputReason, null, 0, 0, 0));
return false;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index d11fa5f01ac1..da786f3a95be 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -99,14 +99,14 @@ import android.text.BoringLayout;
import android.text.DynamicLayout;
import android.text.Editable;
import android.text.GetChars;
-import android.text.GraphemeClusterSegmentIterator;
+import android.text.GraphemeClusterSegmentFinder;
import android.text.GraphicsOperations;
import android.text.InputFilter;
import android.text.InputType;
import android.text.Layout;
import android.text.ParcelableSpan;
import android.text.PrecomputedText;
-import android.text.SegmentIterator;
+import android.text.SegmentFinder;
import android.text.Selection;
import android.text.SpanWatcher;
import android.text.Spannable;
@@ -120,7 +120,7 @@ import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextUtils.TruncateAt;
import android.text.TextWatcher;
-import android.text.WordSegmentIterator;
+import android.text.WordSegmentFinder;
import android.text.method.AllCapsTransformationMethod;
import android.text.method.ArrowKeyMovementMethod;
import android.text.method.DateKeyListener;
@@ -9515,16 +9515,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
@Nullable
private int[] getRangeForRect(@NonNull RectF area, int granularity) {
- SegmentIterator segmentIterator;
+ SegmentFinder segmentFinder;
if (granularity == HandwritingGesture.GRANULARITY_WORD) {
WordIterator wordIterator = getWordIterator();
wordIterator.setCharSequence(mText, 0, mText.length());
- segmentIterator = new WordSegmentIterator(mText, wordIterator);
+ segmentFinder = new WordSegmentFinder(mText, wordIterator);
} else {
- segmentIterator = new GraphemeClusterSegmentIterator(mText, mTextPaint);
+ segmentFinder = new GraphemeClusterSegmentFinder(mText, mTextPaint);
}
- return mLayout.getRangeForRect(area, segmentIterator);
+ return mLayout.getRangeForRect(
+ area, segmentFinder, Layout.INCLUSION_STRATEGY_CONTAINS_CENTER);
}
private Pattern getWhitespacePattern() {
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 3732ea5abaa5..787b594af6bb 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -84,6 +84,11 @@ interface IBatteryStats {
@RequiresNoPermission
long computeChargeTimeRemaining();
+ @EnforcePermission("BATTERY_STATS")
+ long computeBatteryScreenOffRealtimeMs();
+ @EnforcePermission("BATTERY_STATS")
+ long getScreenOffDischargeMah();
+
@EnforcePermission("UPDATE_DEVICE_STATS")
void noteEvent(int code, String name, int uid);
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index 9f15469f4046..f4c3928ac72f 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -84,6 +84,7 @@ interface IInputMethodManager {
void showInputMethodPickerFromSystem(in IInputMethodClient client,
int auxiliarySubtypeMode, int displayId);
+ @EnforcePermission("TEST_INPUT_METHOD")
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(value = "
+ "android.Manifest.permission.TEST_INPUT_METHOD)")
boolean isInputMethodPickerShownForTest();
diff --git a/core/jni/android_media_AudioVolumeGroups.cpp b/core/jni/android_media_AudioVolumeGroups.cpp
index 7098451901c4..1252e89935e5 100644
--- a/core/jni/android_media_AudioVolumeGroups.cpp
+++ b/core/jni/android_media_AudioVolumeGroups.cpp
@@ -94,6 +94,11 @@ static jint convertAudioVolumeGroupsFromNative(
for (size_t j = 0; j < static_cast<size_t>(numAttributes); j++) {
auto attributes = group.getAudioAttributes()[j];
+ // Native & Java audio attributes default initializers are not aligned for the source.
+ // Given the volume group class concerns only playback, this field must be equal to the
+ // default java initializer.
+ attributes.source = AUDIO_SOURCE_INVALID;
+
jStatus = JNIAudioAttributeHelper::nativeToJava(env, &jAudioAttribute, attributes);
if (jStatus != AUDIO_JAVA_SUCCESS) {
goto exit;
diff --git a/core/jni/android_os_Trace.cpp b/core/jni/android_os_Trace.cpp
index 1c61c7be4414..ffacd9c8a95b 100644
--- a/core/jni/android_os_Trace.cpp
+++ b/core/jni/android_os_Trace.cpp
@@ -22,6 +22,8 @@
#include <array>
+static constexpr const char* kNullReplacement = "(null)";
+
namespace android {
inline static void sanitizeString(char* str) {
@@ -36,6 +38,11 @@ inline static void sanitizeString(char* str) {
template<typename F>
inline static void withString(JNIEnv* env, jstring jstr, F callback) {
+ if (CC_UNLIKELY(jstr == nullptr)) {
+ callback(kNullReplacement);
+ return;
+ }
+
// We need to handle the worst case of 1 character -> 4 bytes
// So make a buffer of size 4097 and let it hold a string with a maximum length
// of 1024. The extra last byte for the null terminator.
@@ -52,14 +59,14 @@ inline static void withString(JNIEnv* env, jstring jstr, F callback) {
static void android_os_Trace_nativeTraceCounter(JNIEnv* env, jclass,
jlong tag, jstring nameStr, jlong value) {
- withString(env, nameStr, [tag, value](char* str) {
+ withString(env, nameStr, [tag, value](const char* str) {
atrace_int64(tag, str, value);
});
}
static void android_os_Trace_nativeTraceBegin(JNIEnv* env, jclass,
jlong tag, jstring nameStr) {
- withString(env, nameStr, [tag](char* str) {
+ withString(env, nameStr, [tag](const char* str) {
atrace_begin(tag, str);
});
}
@@ -70,22 +77,22 @@ static void android_os_Trace_nativeTraceEnd(JNIEnv*, jclass, jlong tag) {
static void android_os_Trace_nativeAsyncTraceBegin(JNIEnv* env, jclass,
jlong tag, jstring nameStr, jint cookie) {
- withString(env, nameStr, [tag, cookie](char* str) {
+ withString(env, nameStr, [tag, cookie](const char* str) {
atrace_async_begin(tag, str, cookie);
});
}
static void android_os_Trace_nativeAsyncTraceEnd(JNIEnv* env, jclass,
jlong tag, jstring nameStr, jint cookie) {
- withString(env, nameStr, [tag, cookie](char* str) {
+ withString(env, nameStr, [tag, cookie](const char* str) {
atrace_async_end(tag, str, cookie);
});
}
static void android_os_Trace_nativeAsyncTraceForTrackBegin(JNIEnv* env, jclass,
jlong tag, jstring trackStr, jstring nameStr, jint cookie) {
- withString(env, trackStr, [env, tag, nameStr, cookie](char* track) {
- withString(env, nameStr, [tag, track, cookie](char* name) {
+ withString(env, trackStr, [env, tag, nameStr, cookie](const char* track) {
+ withString(env, nameStr, [tag, track, cookie](const char* name) {
atrace_async_for_track_begin(tag, track, name, cookie);
});
});
@@ -93,7 +100,7 @@ static void android_os_Trace_nativeAsyncTraceForTrackBegin(JNIEnv* env, jclass,
static void android_os_Trace_nativeAsyncTraceForTrackEnd(JNIEnv* env, jclass,
jlong tag, jstring trackStr, jint cookie) {
- withString(env, trackStr, [tag, cookie](char* track) {
+ withString(env, trackStr, [tag, cookie](const char* track) {
atrace_async_for_track_end(tag, track, cookie);
});
}
@@ -108,15 +115,15 @@ static void android_os_Trace_nativeSetTracingEnabled(JNIEnv*, jclass, jboolean e
static void android_os_Trace_nativeInstant(JNIEnv* env, jclass,
jlong tag, jstring nameStr) {
- withString(env, nameStr, [tag](char* str) {
+ withString(env, nameStr, [tag](const char* str) {
atrace_instant(tag, str);
});
}
static void android_os_Trace_nativeInstantForTrack(JNIEnv* env, jclass,
jlong tag, jstring trackStr, jstring nameStr) {
- withString(env, trackStr, [env, tag, nameStr](char* track) {
- withString(env, nameStr, [tag, track](char* name) {
+ withString(env, trackStr, [env, tag, nameStr](const char* track) {
+ withString(env, nameStr, [tag, track](const char* name) {
atrace_instant_for_track(tag, track, name);
});
});
diff --git a/core/tests/coretests/src/android/os/TraceTest.java b/core/tests/coretests/src/android/os/TraceTest.java
index 5cad549d39bf..d07187c2c9d8 100644
--- a/core/tests/coretests/src/android/os/TraceTest.java
+++ b/core/tests/coretests/src/android/os/TraceTest.java
@@ -33,7 +33,21 @@ public class TraceTest extends AndroidTestCase
private int eMethodCalls = 0;
private int fMethodCalls = 0;
private int gMethodCalls = 0;
-
+
+ public void testNullStrings() {
+ Trace.traceCounter(Trace.TRACE_TAG_ACTIVITY_MANAGER, null, 42);
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, null);
+
+ Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, null, 42);
+ Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, null, 42);
+
+ Trace.asyncTraceForTrackBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, null, null, 42);
+ Trace.asyncTraceForTrackEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, null, 42);
+
+ Trace.instant(Trace.TRACE_TAG_ACTIVITY_MANAGER, null);
+ Trace.instantForTrack(Trace.TRACE_TAG_ACTIVITY_MANAGER, null, null);
+ }
+
@SmallTest
public void testNativeTracingFromJava()
{
diff --git a/core/tests/coretests/src/android/text/LayoutGetRangeForRectTest.java b/core/tests/coretests/src/android/text/LayoutGetRangeForRectTest.java
deleted file mode 100644
index 787a4055b49d..000000000000
--- a/core/tests/coretests/src/android/text/LayoutGetRangeForRectTest.java
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.text;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.graphics.RectF;
-import android.graphics.Typeface;
-import android.text.method.WordIterator;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class LayoutGetRangeForRectTest {
-
- private static final int WIDTH = 200;
- private static final int HEIGHT = 1000;
- private static final String DEFAULT_TEXT = ""
- // Line 0 (offset 0 to 18)
- // - Word 0 (offset 0 to 4) has bounds [0, 40], center 20
- // - Word 1 (offset 5 to 11) has bounds [50, 110], center 80
- // - Word 2 (offset 12 to 17) has bounds [120, 170], center 145
- + "XXXX XXXXXX XXXXX "
- // Line 1 (offset 18 to 36)
- // - Word 3 (offset 18 to 23) has bounds [0, 50], center 25
- // - Word 4 (offset 24 to 26, RTL) has bounds [100, 110], center 105
- // - Word 5 (offset 27 to 29, RTL) has bounds [80, 90], center 85
- // - Word 6 start part (offset 30 to 32, RTL) has bounds [60, 70], center 65
- // - Word 6 end part (offset 32 to 35) has bounds [110, 140], center 125
- + "XXXXX \u05D1\u05D1 \u05D1\u05D1 \u05D1\u05D1XXX\n"
- // Line 2 (offset 36 to 38)
- // - Word 7 start part (offset 36 to 38) has bounds [0, 150], center 75
- // Line 3 (offset 38 to 40)
- // - Word 7 middle part (offset 38 to 40) has bounds [0, 150], center 75
- // Line 4 (offset 40 to 46)
- // - Word 7 end part (offset 40 to 41) has bounds [0, 100], center 50
- // - Word 8 (offset 42 to 44) has bounds [110, 130], center 120
- + "CLCLC XX \n";
-
- private Layout mLayout;
- private float[] mLineCenters;
- private GraphemeClusterSegmentIterator mGraphemeClusterSegmentIterator;
- private WordSegmentIterator mWordSegmentIterator;
-
- @Before
- public void setup() {
- // The test font includes the following characters:
- // U+0020 ( ): 10em
- // U+002E (.): 10em
- // U+0049 (I): 1em
- // U+0056 (V): 5em
- // U+0058 (X): 10em
- // U+004C (L): 50em
- // U+0043 (C): 100em
- // U+005F (_): 0em
- // U+05D0 : 1em // HEBREW LETTER ALEF
- // U+05D1 : 5em // HEBREW LETTER BET
- // U+FFFD (invalid surrogate will be replaced to this): 7em
- // U+10331 (\uD800\uDF31): 10em
- // Undefined : 0.5em
- TextPaint textPaint = new TextPaint();
- textPaint.setTypeface(
- Typeface.createFromAsset(
- InstrumentationRegistry.getInstrumentation().getTargetContext().getAssets(),
- "fonts/StaticLayoutLineBreakingTestFont.ttf"));
- // Make 1 em equal to 1 pixel.
- textPaint.setTextSize(1.0f);
-
- mLayout = StaticLayout.Builder.obtain(
- DEFAULT_TEXT, 0, DEFAULT_TEXT.length(), textPaint, WIDTH).build();
-
- mLineCenters = new float[mLayout.getLineCount()];
- for (int i = 0; i < mLayout.getLineCount(); ++i) {
- mLineCenters[i] = (mLayout.getLineTop(i)
- + mLayout.getLineBottom(i, /* includeLineSpacing= */ false)) / 2f;
- }
-
- mGraphemeClusterSegmentIterator =
- new GraphemeClusterSegmentIterator(DEFAULT_TEXT, textPaint);
- WordIterator wordIterator = new WordIterator();
- wordIterator.setCharSequence(DEFAULT_TEXT, 0, DEFAULT_TEXT.length());
- mWordSegmentIterator = new WordSegmentIterator(DEFAULT_TEXT, wordIterator);
- }
-
- @Test
- public void getRangeForRect_character() {
- // Character 1 on line 0 has center 15.
- // Character 2 on line 0 has center 25.
- RectF area = new RectF(14f, mLineCenters[0] - 1f, 26f, mLineCenters[0] + 1f);
-
- int[] range = mLayout.getRangeForRect(area, mGraphemeClusterSegmentIterator);
-
- assertThat(range).asList().containsExactly(1, 3).inOrder();
- }
-
- @Test
- public void getRangeForRect_character_partialCharacterButNotCenter() {
- // Character 0 on line 0 has center 5.
- // Character 1 on line 0 has center 15.
- // Character 2 on line 0 has center 25.
- // Character 3 on line 0 has center 35.
- RectF area = new RectF(6f, mLineCenters[0] - 1f, 34f, mLineCenters[0] + 1f);
- int[] range = mLayout.getRangeForRect(area, mGraphemeClusterSegmentIterator);
-
- // Area partially overlaps characters 0 and 3 but does not contain their centers.
- assertThat(range).asList().containsExactly(1, 3).inOrder();
- }
-
- @Test
- public void getRangeForRect_character_rtl() {
- // Character 25 on line 1 has center 102.5.
- // Character 26 on line 1 has center 95.
- RectF area = new RectF(94f, mLineCenters[1] - 1f, 103f, mLineCenters[1] + 1f);
- int[] range = mLayout.getRangeForRect(area, mGraphemeClusterSegmentIterator);
-
- assertThat(range).asList().containsExactly(25, 27).inOrder();
- }
-
- @Test
- public void getRangeForRect_character_ltrAndRtl() {
- // Character 22 on line 1 has center 45.
- // The end of the RTL run (offset 24 to 32) on line 1 is at 60.
- RectF area = new RectF(44f, mLineCenters[1] - 1f, 93f, mLineCenters[1] + 1f);
- int[] range = mLayout.getRangeForRect(area, mGraphemeClusterSegmentIterator);
-
- assertThat(range).asList().containsExactly(22, 32).inOrder();
- }
-
- @Test
- public void getRangeForRect_character_rtlAndLtr() {
- // The start of the RTL run (offset 24 to 32) on line 1 is at 110.
- // Character 33 on line 1 has center 125.
- RectF area = new RectF(93f, mLineCenters[1] - 1f, 131f, mLineCenters[1] + 1f);
- int[] range = mLayout.getRangeForRect(area, mGraphemeClusterSegmentIterator);
-
- assertThat(range).asList().containsExactly(24, 34).inOrder();
- }
-
- @Test
- public void getRangeForRect_character_betweenCharacters_shouldFallback() {
- // Character 1 on line 0 has center 15.
- // Character 2 on line 0 has center 25.
- RectF area = new RectF(16f, mLineCenters[0] - 1f, 24f, mLineCenters[0] + 1f);
- int[] range = mLayout.getRangeForRect(area, mGraphemeClusterSegmentIterator);
-
- assertThat(range).isNull();
- }
-
- @Test
- public void getRangeForRect_character_betweenLines_shouldFallback() {
- // Area top is below the center of line 0.
- // Area bottom is above the center of line 1.
- RectF area = new RectF(0f, mLineCenters[0] + 1f, WIDTH, mLineCenters[1] - 1f);
- int[] range = mLayout.getRangeForRect(area, mGraphemeClusterSegmentIterator);
-
- // Area partially covers two lines but does not contain the center of any characters.
- assertThat(range).isNull();
- }
-
- @Test
- public void getRangeForRect_character_multiLine() {
- // Character 9 on line 0 has center 95.
- // Character 42 on line 4 has center 115.
- RectF area = new RectF(93f, 0, 118f, HEIGHT);
- int[] range = mLayout.getRangeForRect(area, mGraphemeClusterSegmentIterator);
-
- assertThat(range).asList().containsExactly(9, 43).inOrder();
- }
-
- @Test
- public void getRangeForRect_character_multiLine_betweenCharactersOnSomeLines() {
- // Character 6 on line 0 has center 65.
- // Character 7 on line 0 has center 75.
- // Character 30 on line 1 has center 67.5.
- // Character 36 on line 2 has center 50.
- // Character 37 on line 2 has center 125.
- // Character 38 on line 3 has center 50.
- // Character 39 on line 3 has center 125.
- // Character 40 on line 4 has center 50.
- // Character 41 on line 4 has center 105.
- RectF area = new RectF(66f, 0, 69f, HEIGHT);
- int[] range = mLayout.getRangeForRect(area, mGraphemeClusterSegmentIterator);
-
- // Area crosses all lines but does not contain the center of any characters on lines 0, 2,
- // 3, or 4. So the only included character is character 30 on line 1.
- assertThat(range).asList().containsExactly(30, 31).inOrder();
- }
-
- @Test
- public void getRangeForRect_character_multiLine_betweenCharactersOnAllLines_shouldFallback() {
- // Character 6 on line 0 has center 65.
- // Character 7 on line 0 has center 75.
- // Character 30 on line 1 has center 67.5.
- // Character 31 on line 1 has center 62.5.
- // Character 36 on line 2 has center 50.
- // Character 37 on line 2 has center 125.
- // Character 38 on line 3 has center 50.
- // Character 39 on line 3 has center 125.
- // Character 40 on line 4 has center 50.
- // Character 41 on line 4 has center 105.
- RectF area = new RectF(66f, 0, 67f, HEIGHT);
- int[] range = mLayout.getRangeForRect(area, mGraphemeClusterSegmentIterator);
-
- // Area crosses all lines but does not contain the center of any characters.
- assertThat(range).isNull();
- }
-
- @Test
- public void getRangeForRect_character_all() {
- // Entire area, should include all text.
- RectF area = new RectF(0f, 0f, WIDTH, HEIGHT);
- int[] range = mLayout.getRangeForRect(area, mGraphemeClusterSegmentIterator);
-
- assertThat(range).asList().containsExactly(0, DEFAULT_TEXT.length()).inOrder();
- }
-
- @Test
- public void getRangeForRect_word() {
- // Word 1 (offset 5 to 11) on line 0 has center 80.
- RectF area = new RectF(79f, mLineCenters[0] - 1f, 81f, mLineCenters[0] + 1f);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- assertThat(range).asList().containsExactly(5, 11).inOrder();
- }
-
- @Test
- public void getRangeForRect_word_partialWordButNotCenter() {
- // Word 0 (offset 0 to 4) on line 0 has center 20.
- // Word 1 (offset 5 to 11) on line 0 has center 80.
- // Word 2 (offset 12 to 17) on line 0 center 145
- RectF area = new RectF(21f, mLineCenters[0] - 1f, 144f, mLineCenters[0] + 1f);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- // Area partially overlaps words 0 and 2 but does not contain their centers, so only word 1
- // is included. Whitespace between words is not included.
- assertThat(range).asList().containsExactly(5, 11).inOrder();
- }
-
- @Test
- public void getRangeForRect_word_rtl() {
- // Word 4 (offset 24 to 26, RTL) on line 1 center 105
- RectF area = new RectF(88f, mLineCenters[1] - 1f, 119f, mLineCenters[1] + 1f);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- assertThat(range).asList().containsExactly(24, 26).inOrder();
- }
-
- @Test
- public void getRangeForRect_word_ltrAndRtl() {
- // Word 3 (offset 18 to 23) on line 1 has center 25
- // The end of the RTL run (offset 24 to 32) on line 1 is at 60.
- RectF area = new RectF(24f, mLineCenters[1] - 1f, 93f, mLineCenters[1] + 1f);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- // Selects all of word 6, not just the first RTL part.
- assertThat(range).asList().containsExactly(18, 35).inOrder();
- }
-
- @Test
- public void getRangeForRect_word_rtlAndLtr() {
- // The start of the RTL run (offset 24 to 32) on line 1 is at 110.
- // End part of word 6 (offset 32 to 35) on line 1 has center 125.
- RectF area = new RectF(93f, mLineCenters[1] - 1f, 174f, mLineCenters[1] + 1f);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- assertThat(range).asList().containsExactly(24, 35).inOrder();
- }
-
- @Test
- public void getRangeForRect_word_betweenWords_shouldFallback() {
- // Word 1 on line 0 has center 80.
- // Word 2 on line 0 has center 145.
- RectF area = new RectF(81f, mLineCenters[0] - 1f, 144f, mLineCenters[0] + 1f);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- assertThat(range).isNull();
- }
-
- @Test
- public void getRangeForRect_word_betweenLines_shouldFallback() {
- // Area top is below the center of line 0.
- // Area bottom is above the center of line 1.
- RectF area = new RectF(0f, mLineCenters[0] + 1f, WIDTH, mLineCenters[1] - 1f);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- // Area partially covers two lines but does not contain the center of any words.
- assertThat(range).isNull();
- }
-
- @Test
- public void getRangeForRect_word_multiLine() {
- // Word 1 (offset 5 to 11) on line 0 has center 80.
- // End part of word 7 (offset 40 to 41) on line 4 has center 50.
- RectF area = new RectF(42f, 0, 91f, HEIGHT);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- assertThat(range).asList().containsExactly(5, 41).inOrder();
- }
-
- @Test
- public void getRangeForRect_word_multiLine_betweenWordsOnSomeLines() {
- // Word 1 on line 0 has center 80.
- // Word 2 on line 0 has center 145.
- // Word 5 (offset 27 to 29) on line 1 has center 85.
- // Word 7 on line 2 has center 50.
- // Word 37 on line 2 has center 125.
- // Word 38 on line 3 has center 50.
- // Word 39 on line 3 has center 125.
- // Word 40 on line 4 has center 50.
- // Word 41 on line 4 has center 105.
- RectF area = new RectF(84f, 0, 86f, HEIGHT);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- // Area crosses all lines but does not contain the center of any words on lines 0, 2, 3, or
- // 4. So the only included word is word 5 on line 1.
- assertThat(range).asList().containsExactly(27, 29).inOrder();
- }
-
- @Test
- public void getRangeForRect_word_multiLine_betweenCharactersOnAllLines_shouldFallback() {
- // Word 1 on line 0 has center 80.
- // Word 2 on line 0 has center 145.
- // Word 4 on line 1 has center 105.
- // Word 5 on line 1 has center 85.
- // Word 7 on line 2 has center 50.
- // Word 37 on line 2 has center 125.
- // Word 38 on line 3 has center 50.
- // Word 39 on line 3 has center 125.
- // Word 40 on line 4 has center 50.
- // Word 41 on line 4 has center 105.
- RectF area = new RectF(86f, 0, 89f, HEIGHT);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- // Area crosses all lines but does not contain the center of any words.
- assertThat(range).isNull();
- }
-
- @Test
- public void getRangeForRect_word_wordSpansMultipleLines_firstPartInsideArea() {
- // Word 5 (offset 27 to 29) on line 1 has center 85.
- // First part of word 7 (offset 36 to 38) on line 2 has center 75.
- RectF area = new RectF(74f, mLineCenters[1] - 1f, 86f, mLineCenters[2] + 1f);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- // Selects all of word 7, not just the first part on line 2.
- assertThat(range).asList().containsExactly(27, 41).inOrder();
- }
-
- @Test
- public void getRangeForRect_word_wordSpansMultipleLines_middlePartInsideArea() {
- // Middle part of word 7 (offset 38 to 40) on line 2 has center 75.
- RectF area = new RectF(74f, mLineCenters[3] - 1f, 75f, mLineCenters[3] + 1f);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- // Selects all of word 7, not just the middle part on line 3.
- assertThat(range).asList().containsExactly(36, 41).inOrder();
- }
-
- @Test
- public void getRangeForRect_word_wordSpansMultipleLines_endPartInsideArea() {
- // End part of word 7 (offset 40 to 41) on line 4 has center 50.
- // Word 8 (offset 42 to 44) on line 4 has center 120
- RectF area = new RectF(49f, mLineCenters[4] - 1f, 121f, mLineCenters[4] + 1f);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- // Selects all of word 7, not just the middle part on line 3.
- assertThat(range).asList().containsExactly(36, 44).inOrder();
- }
-
- @Test
- public void getRangeForRect_word_wordSpansMultipleRuns_firstPartInsideArea() {
- // Word 5 (offset 27 to 29) on line 1 has center 85.
- // First part of word 6 (offset 30 to 32) on line 1 has center 65.
- RectF area = new RectF(64f, mLineCenters[1] - 1f, 86f, mLineCenters[1] + 1f);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- // Selects all of word 6, not just the first RTL part.
- assertThat(range).asList().containsExactly(27, 35).inOrder();
- }
-
- @Test
- public void getRangeForRect_word_all() {
- // Entire area, should include all text except the last two whitespace characters.
- RectF area = new RectF(0f, 0f, WIDTH, HEIGHT);
- int[] range = mLayout.getRangeForRect(area, mWordSegmentIterator);
-
- assertThat(range).asList().containsExactly(0, DEFAULT_TEXT.length() - 2).inOrder();
- }
-}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java
index b631999c2c54..4e73bd9d3c82 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java
@@ -18,13 +18,19 @@ package android.security.keystore2;
import android.annotation.NonNull;
import android.security.KeyStoreSecurityLevel;
+import android.security.keymaster.KeymasterDefs;
import android.security.keystore.KeyProperties;
+import android.system.keystore2.Authorization;
import android.system.keystore2.KeyDescriptor;
import android.system.keystore2.KeyMetadata;
+import java.security.AlgorithmParameters;
+import java.security.NoSuchAlgorithmException;
import java.security.interfaces.ECPublicKey;
+import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
+import java.security.spec.InvalidParameterSpecException;
/**
* {@link ECPublicKey} backed by keystore.
@@ -56,11 +62,45 @@ public class AndroidKeyStoreECPublicKey extends AndroidKeyStorePublicKey impleme
}
}
+ private static String getEcCurveFromKeymaster(int ecCurve) {
+ switch (ecCurve) {
+ case android.hardware.security.keymint.EcCurve.P_224:
+ return "secp224r1";
+ case android.hardware.security.keymint.EcCurve.P_256:
+ return "secp256r1";
+ case android.hardware.security.keymint.EcCurve.P_384:
+ return "secp384r1";
+ case android.hardware.security.keymint.EcCurve.P_521:
+ return "secp521r1";
+ }
+ return "";
+ }
+
+ private ECParameterSpec getCurveSpec(String name)
+ throws NoSuchAlgorithmException, InvalidParameterSpecException {
+ AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC");
+ parameters.init(new ECGenParameterSpec(name));
+ return parameters.getParameterSpec(ECParameterSpec.class);
+ }
+
@Override
public AndroidKeyStorePrivateKey getPrivateKey() {
+ ECParameterSpec params = mParams;
+ for (Authorization a : getAuthorizations()) {
+ try {
+ if (a.keyParameter.tag == KeymasterDefs.KM_TAG_EC_CURVE) {
+ params = getCurveSpec(getEcCurveFromKeymaster(
+ a.keyParameter.value.getEcCurve()));
+ break;
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to parse EC curve "
+ + a.keyParameter.value.getEcCurve());
+ }
+ }
return new AndroidKeyStoreECPrivateKey(
getUserKeyDescriptor(), getKeyIdDescriptor().nspace, getAuthorizations(),
- getSecurityLevel(), mParams);
+ getSecurityLevel(), params);
}
@Override
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java
index b1338d164055..4caa47f2078b 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java
@@ -31,6 +31,8 @@ import java.security.NoSuchAlgorithmException;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.SecureRandom;
+import java.security.interfaces.ECKey;
+import java.security.interfaces.XECKey;
import java.security.spec.AlgorithmParameterSpec;
import java.util.ArrayList;
import java.util.List;
@@ -132,6 +134,15 @@ public class AndroidKeyStoreKeyAgreementSpi extends KeyAgreementSpi
throw new InvalidKeyException("key == null");
} else if (!(key instanceof PublicKey)) {
throw new InvalidKeyException("Only public keys supported. Key: " + key);
+ } else if (!(mKey instanceof ECKey && key instanceof ECKey)
+ && !(mKey instanceof XECKey && key instanceof XECKey)) {
+ throw new InvalidKeyException(
+ "Public and Private key should be of the same type:");
+ } else if (mKey instanceof ECKey
+ && !((ECKey) key).getParams().getCurve()
+ .equals(((ECKey) mKey).getParams().getCurve())) {
+ throw new InvalidKeyException(
+ "Public and Private key parameters should be same.");
} else if (!lastPhase) {
throw new IllegalStateException(
"Only one other party supported. lastPhase must be set to true.");
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java
index 42589640d2b7..e392c8dcca93 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPrivateKey.java
@@ -22,16 +22,18 @@ import android.system.keystore2.Authorization;
import android.system.keystore2.KeyDescriptor;
import java.security.PrivateKey;
-import java.security.interfaces.EdECKey;
+import java.security.interfaces.XECPrivateKey;
import java.security.spec.NamedParameterSpec;
+import java.util.Optional;
/**
* X25519 Private Key backed by Keystore.
- * instance of {@link PrivateKey} and {@link EdECKey}
+ * instance of {@link PrivateKey} and {@link XECPrivateKey}
*
* @hide
*/
-public class AndroidKeyStoreXDHPrivateKey extends AndroidKeyStorePrivateKey implements EdECKey {
+public class AndroidKeyStoreXDHPrivateKey extends AndroidKeyStorePrivateKey
+ implements XECPrivateKey {
public AndroidKeyStoreXDHPrivateKey(
@NonNull KeyDescriptor descriptor, long keyId,
@NonNull Authorization[] authorizations,
@@ -44,4 +46,12 @@ public class AndroidKeyStoreXDHPrivateKey extends AndroidKeyStorePrivateKey impl
public NamedParameterSpec getParams() {
return NamedParameterSpec.X25519;
}
+
+ @Override
+ public Optional<byte[]> getScalar() {
+ /* An empty Optional if the scalar cannot be extracted (e.g. if the provider is a hardware
+ * token and the private key is not allowed to leave the crypto boundary).
+ */
+ return Optional.empty();
+ }
}
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 c4accde23d93..3b735fce3fa9 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
@@ -69,7 +69,6 @@ import com.android.wm.shell.floating.FloatingTasksController;
import com.android.wm.shell.freeform.FreeformComponents;
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutoutController;
-import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.Pip;
@@ -192,25 +191,6 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
- static KidsModeTaskOrganizer provideKidsModeTaskOrganizer(
- Context context,
- ShellInit shellInit,
- ShellCommandHandler shellCommandHandler,
- SyncTransactionQueue syncTransactionQueue,
- DisplayController displayController,
- DisplayInsetsController displayInsetsController,
- Optional<UnfoldAnimationController> unfoldAnimationController,
- Optional<RecentTasksController> recentTasksOptional,
- @ShellMainThread ShellExecutor mainExecutor,
- @ShellMainThread Handler mainHandler
- ) {
- return new KidsModeTaskOrganizer(context, shellInit, shellCommandHandler,
- syncTransactionQueue, displayController, displayInsetsController,
- unfoldAnimationController, recentTasksOptional, mainExecutor, mainHandler);
- }
-
- @WMSingleton
- @Provides
static CompatUIController provideCompatUIController(Context context,
ShellInit shellInit,
ShellController shellController,
@@ -782,7 +762,6 @@ public abstract class WMShellBaseModule {
DisplayInsetsController displayInsetsController,
DragAndDropController dragAndDropController,
ShellTaskOrganizer shellTaskOrganizer,
- KidsModeTaskOrganizer kidsModeTaskOrganizer,
Optional<BubbleController> bubblesOptional,
Optional<SplitScreenController> splitScreenOptional,
Optional<Pip> pipOptional,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 37a50b611039..47b665970d28 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -56,6 +56,7 @@ import com.android.wm.shell.freeform.FreeformTaskListener;
import com.android.wm.shell.freeform.FreeformTaskTransitionHandler;
import com.android.wm.shell.freeform.FreeformTaskTransitionObserver;
import com.android.wm.shell.fullscreen.FullscreenTaskListener;
+import com.android.wm.shell.kidsmode.KidsModeTaskOrganizer;
import com.android.wm.shell.onehanded.OneHandedController;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.pip.PipAnimationController;
@@ -620,6 +621,28 @@ public abstract class WMShellModule {
}
//
+ // Kids mode
+ //
+ @WMSingleton
+ @Provides
+ static KidsModeTaskOrganizer provideKidsModeTaskOrganizer(
+ Context context,
+ ShellInit shellInit,
+ ShellCommandHandler shellCommandHandler,
+ SyncTransactionQueue syncTransactionQueue,
+ DisplayController displayController,
+ DisplayInsetsController displayInsetsController,
+ Optional<UnfoldAnimationController> unfoldAnimationController,
+ Optional<RecentTasksController> recentTasksOptional,
+ @ShellMainThread ShellExecutor mainExecutor,
+ @ShellMainThread Handler mainHandler
+ ) {
+ return new KidsModeTaskOrganizer(context, shellInit, shellCommandHandler,
+ syncTransactionQueue, displayController, displayInsetsController,
+ unfoldAnimationController, recentTasksOptional, mainExecutor, mainHandler);
+ }
+
+ //
// Misc
//
@@ -630,6 +653,7 @@ public abstract class WMShellModule {
@Provides
static Object provideIndependentShellComponentsToCreate(
DefaultMixedHandler defaultMixedHandler,
+ KidsModeTaskOrganizer kidsModeTaskOrganizer,
Optional<DesktopModeController> desktopModeController) {
return new Object();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
index 4def15db2f52..2624ee536b58 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/IPip.aidl
@@ -59,10 +59,15 @@ interface IPip {
/**
* Sets listener to get pinned stack animation callbacks.
*/
- oneway void setPinnedStackAnimationListener(IPipAnimationListener listener) = 3;
+ oneway void setPipAnimationListener(IPipAnimationListener listener) = 3;
/**
* Sets the shelf height and visibility.
*/
oneway void setShelfHeight(boolean visible, int shelfHeight) = 4;
+
+ /**
+ * Sets the next pip animation type to be the alpha animation.
+ */
+ oneway void setPipAnimationTypeToAlpha() = 5;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
index c06881ae6ad7..72b9dd37ac7d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/Pip.java
@@ -51,15 +51,6 @@ public interface Pip {
}
/**
- * Sets both shelf visibility and its height.
- *
- * @param visible visibility of shelf.
- * @param height to specify the height for shelf.
- */
- default void setShelfHeight(boolean visible, int height) {
- }
-
- /**
* Set the callback when {@link PipTaskOrganizer#isInPip()} state is changed.
*
* @param callback The callback accepts the result of {@link PipTaskOrganizer#isInPip()}
@@ -68,14 +59,6 @@ public interface Pip {
default void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) {}
/**
- * Set the pinned stack with {@link PipAnimationController.AnimationType}
- *
- * @param animationType The pre-defined {@link PipAnimationController.AnimationType}
- */
- default void setPinnedStackAnimationType(int animationType) {
- }
-
- /**
* Called when showing Pip menu.
*/
default void showPictureInPictureMenu() {}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index af47666efa5a..3345b1b2d0e8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -23,6 +23,7 @@ import static android.view.WindowManager.INPUT_CONSUMER_PIP;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_PIP_TRANSITION;
import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
+import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN;
@@ -1065,13 +1066,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
@Override
- public void setShelfHeight(boolean visible, int height) {
- mMainExecutor.execute(() -> {
- PipController.this.setShelfHeight(visible, height);
- });
- }
-
- @Override
public void setOnIsInPipStateChangedListener(Consumer<Boolean> callback) {
mMainExecutor.execute(() -> {
PipController.this.setOnIsInPipStateChangedListener(callback);
@@ -1079,13 +1073,6 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
@Override
- public void setPinnedStackAnimationType(int animationType) {
- mMainExecutor.execute(() -> {
- PipController.this.setPinnedStackAnimationType(animationType);
- });
- }
-
- @Override
public void addPipExclusionBoundsChangeListener(Consumer<Rect> listener) {
mMainExecutor.execute(() -> {
mPipBoundsState.addPipExclusionBoundsChangeCallback(listener);
@@ -1178,8 +1165,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
@Override
- public void setPinnedStackAnimationListener(IPipAnimationListener listener) {
- executeRemoteCallWithTaskPermission(mController, "setPinnedStackAnimationListener",
+ public void setPipAnimationListener(IPipAnimationListener listener) {
+ executeRemoteCallWithTaskPermission(mController, "setPipAnimationListener",
(controller) -> {
if (listener != null) {
mListener.register(listener);
@@ -1188,5 +1175,13 @@ public class PipController implements PipTransitionController.PipTransitionCallb
}
});
}
+
+ @Override
+ public void setPipAnimationTypeToAlpha() {
+ executeRemoteCallWithTaskPermission(mController, "setPipAnimationTypeToAlpha",
+ (controller) -> {
+ controller.setPinnedStackAnimationType(ANIM_TYPE_ALPHA);
+ });
+ }
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
index 85a544b2e8de..4c262249dfa2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/tv/TvPipController.java
@@ -240,12 +240,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
"%s: onConfigurationChanged(), state=%s", TAG, stateToName(mState));
- if (isPipShown()) {
- ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
- "%s: > closing Pip.", TAG);
- closePip();
- }
-
loadConfigurations();
mPipNotificationController.onConfigurationChanged(mContext);
mTvPipBoundsAlgorithm.onConfigurationChanged(mContext);
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
index 2b162aec34ca..c9c894317ff8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/BaseTest.kt
@@ -38,50 +38,44 @@ import org.junit.Test
/**
* Base test class containing common assertions for [ComponentMatcher.NAV_BAR],
- * [ComponentMatcher.TASK_BAR], [ComponentMatcher.STATUS_BAR], and general assertions
- * (layers visible in consecutive states, entire screen covered, etc.)
+ * [ComponentMatcher.TASK_BAR], [ComponentMatcher.STATUS_BAR], and general assertions (layers
+ * visible in consecutive states, entire screen covered, etc.)
*/
-abstract class BaseTest @JvmOverloads constructor(
+abstract class BaseTest
+@JvmOverloads
+constructor(
protected val testSpec: FlickerTestParameter,
protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation(),
protected val tapl: LauncherInstrumentation = LauncherInstrumentation()
) {
init {
testSpec.setIsTablet(
- WindowManagerStateHelper(
- instrumentation,
- clearCacheAfterParsing = false
- ).currentState.wmState.isTablet
+ WindowManagerStateHelper(instrumentation, clearCacheAfterParsing = false)
+ .currentState
+ .wmState
+ .isTablet
)
}
- /**
- * Specification of the test transition to execute
- */
+ /** Specification of the test transition to execute */
abstract val transition: FlickerBuilder.() -> Unit
/**
- * Entry point for the test runner. It will use this method to initialize and cache
- * flicker executions
+ * Entry point for the test runner. It will use this method to initialize and cache flicker
+ * executions
*/
@FlickerBuilderProvider
fun buildFlicker(): FlickerBuilder {
return FlickerBuilder(instrumentation).apply {
- setup {
- testSpec.setIsTablet(wmHelper.currentState.wmState.isTablet)
- }
+ setup { testSpec.setIsTablet(wmHelper.currentState.wmState.isTablet) }
transition()
}
}
- /**
- * Checks that all parts of the screen are covered during the transition
- */
+ /** Checks that all parts of the screen are covered during the transition */
open fun entireScreenCovered() = testSpec.entireScreenCovered()
- /**
- * Checks that the [ComponentMatcher.NAV_BAR] layer is visible during the whole transition
- */
+ /** Checks that the [ComponentMatcher.NAV_BAR] layer is visible during the whole transition */
@Presubmit
@Test
open fun navBarLayerIsVisibleAtStartAndEnd() {
@@ -111,9 +105,7 @@ abstract class BaseTest @JvmOverloads constructor(
testSpec.navBarWindowIsAlwaysVisible()
}
- /**
- * Checks that the [ComponentMatcher.TASK_BAR] layer is visible during the whole transition
- */
+ /** Checks that the [ComponentMatcher.TASK_BAR] layer is visible during the whole transition */
@Presubmit
@Test
open fun taskBarLayerIsVisibleAtStartAndEnd() {
@@ -142,7 +134,8 @@ abstract class BaseTest @JvmOverloads constructor(
testSpec.statusBarLayerIsVisibleAtStartAndEnd()
/**
- * Checks the position of the [ComponentMatcher.STATUS_BAR] at the start and end of the transition
+ * Checks the position of the [ComponentMatcher.STATUS_BAR] at the start and end of the
+ * transition
*/
@Presubmit
@Test
@@ -156,26 +149,22 @@ abstract class BaseTest @JvmOverloads constructor(
open fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
/**
- * Checks that all layers that are visible on the trace, are visible for at least 2
- * consecutive entries.
+ * Checks that all layers that are visible on the trace, are visible for at least 2 consecutive
+ * entries.
*/
@Presubmit
@Test
open fun visibleLayersShownMoreThanOneConsecutiveEntry() {
- testSpec.assertLayers {
- this.visibleLayersShownMoreThanOneConsecutiveEntry()
- }
+ testSpec.assertLayers { this.visibleLayersShownMoreThanOneConsecutiveEntry() }
}
/**
- * Checks that all windows that are visible on the trace, are visible for at least 2
- * consecutive entries.
+ * Checks that all windows that are visible on the trace, are visible for at least 2 consecutive
+ * entries.
*/
@Presubmit
@Test
open fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
- testSpec.assertWm {
- this.visibleWindowsShownMoreThanOneConsecutiveEntry()
- }
+ testSpec.assertWm { this.visibleWindowsShownMoreThanOneConsecutiveEntry() }
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index 6d133779ea60..6f1ff99cb0b3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -15,6 +15,7 @@
*/
@file:JvmName("CommonAssertions")
+
package com.android.wm.shell.flicker
import android.view.Surface
@@ -26,15 +27,11 @@ import com.android.server.wm.traces.common.IComponentMatcher
import com.android.server.wm.traces.common.region.Region
fun FlickerTestParameter.appPairsDividerIsVisibleAtEnd() {
- assertLayersEnd {
- this.isVisible(APP_PAIR_SPLIT_DIVIDER_COMPONENT)
- }
+ assertLayersEnd { this.isVisible(APP_PAIR_SPLIT_DIVIDER_COMPONENT) }
}
fun FlickerTestParameter.appPairsDividerIsInvisibleAtEnd() {
- assertLayersEnd {
- this.notContains(APP_PAIR_SPLIT_DIVIDER_COMPONENT)
- }
+ assertLayersEnd { this.notContains(APP_PAIR_SPLIT_DIVIDER_COMPONENT) }
}
fun FlickerTestParameter.appPairsDividerBecomesVisible() {
@@ -82,27 +79,19 @@ fun FlickerTestParameter.splitScreenDismissed(
}
fun FlickerTestParameter.splitScreenDividerIsVisibleAtStart() {
- assertLayersStart {
- this.isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT)
- }
+ assertLayersStart { this.isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT) }
}
fun FlickerTestParameter.splitScreenDividerIsVisibleAtEnd() {
- assertLayersEnd {
- this.isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT)
- }
+ assertLayersEnd { this.isVisible(SPLIT_SCREEN_DIVIDER_COMPONENT) }
}
fun FlickerTestParameter.splitScreenDividerIsInvisibleAtStart() {
- assertLayersStart {
- this.isInvisible(SPLIT_SCREEN_DIVIDER_COMPONENT)
- }
+ assertLayersStart { this.isInvisible(SPLIT_SCREEN_DIVIDER_COMPONENT) }
}
fun FlickerTestParameter.splitScreenDividerIsInvisibleAtEnd() {
- assertLayersEnd {
- this.isInvisible(SPLIT_SCREEN_DIVIDER_COMPONENT)
- }
+ assertLayersEnd { this.isInvisible(SPLIT_SCREEN_DIVIDER_COMPONENT) }
}
fun FlickerTestParameter.splitScreenDividerBecomesVisible() {
@@ -117,40 +106,20 @@ fun FlickerTestParameter.splitScreenDividerBecomesInvisible() {
}
}
-fun FlickerTestParameter.layerBecomesVisible(
- component: IComponentMatcher
-) {
- assertLayers {
- this.isInvisible(component)
- .then()
- .isVisible(component)
- }
+fun FlickerTestParameter.layerBecomesVisible(component: IComponentMatcher) {
+ assertLayers { this.isInvisible(component).then().isVisible(component) }
}
-fun FlickerTestParameter.layerBecomesInvisible(
- component: IComponentMatcher
-) {
- assertLayers {
- this.isVisible(component)
- .then()
- .isInvisible(component)
- }
+fun FlickerTestParameter.layerBecomesInvisible(component: IComponentMatcher) {
+ assertLayers { this.isVisible(component).then().isInvisible(component) }
}
-fun FlickerTestParameter.layerIsVisibleAtEnd(
- component: IComponentMatcher
-) {
- assertLayersEnd {
- this.isVisible(component)
- }
+fun FlickerTestParameter.layerIsVisibleAtEnd(component: IComponentMatcher) {
+ assertLayersEnd { this.isVisible(component) }
}
-fun FlickerTestParameter.layerKeepVisible(
- component: IComponentMatcher
-) {
- assertLayers {
- this.isVisible(component)
- }
+fun FlickerTestParameter.layerKeepVisible(component: IComponentMatcher) {
+ assertLayers { this.isVisible(component) }
}
fun FlickerTestParameter.splitAppLayerBoundsBecomesVisible(
@@ -164,13 +133,15 @@ fun FlickerTestParameter.splitAppLayerBoundsBecomesVisible(
.isInvisible(SPLIT_SCREEN_DIVIDER_COMPONENT.or(component))
.then()
.splitAppLayerBoundsSnapToDivider(
- component, landscapePosLeft, portraitPosTop, endRotation)
+ component,
+ landscapePosLeft,
+ portraitPosTop,
+ endRotation
+ )
}
}
-fun FlickerTestParameter.splitAppLayerBoundsBecomesVisibleByDrag(
- component: IComponentMatcher
-) {
+fun FlickerTestParameter.splitAppLayerBoundsBecomesVisibleByDrag(component: IComponentMatcher) {
assertLayers {
this.notContains(SPLIT_SCREEN_DIVIDER_COMPONENT.or(component), isOptional = true)
.then()
@@ -188,7 +159,11 @@ fun FlickerTestParameter.splitAppLayerBoundsBecomesInvisible(
) {
assertLayers {
this.splitAppLayerBoundsSnapToDivider(
- component, landscapePosLeft, portraitPosTop, endRotation)
+ component,
+ landscapePosLeft,
+ portraitPosTop,
+ endRotation
+ )
.then()
.isVisible(component, true)
.then()
@@ -224,15 +199,27 @@ fun FlickerTestParameter.splitAppLayerBoundsChanges(
assertLayers {
if (landscapePosLeft) {
this.splitAppLayerBoundsSnapToDivider(
- component, landscapePosLeft, portraitPosTop, endRotation)
+ component,
+ landscapePosLeft,
+ portraitPosTop,
+ endRotation
+ )
} else {
this.splitAppLayerBoundsSnapToDivider(
- component, landscapePosLeft, portraitPosTop, endRotation)
+ component,
+ landscapePosLeft,
+ portraitPosTop,
+ endRotation
+ )
.then()
.isInvisible(component)
.then()
.splitAppLayerBoundsSnapToDivider(
- component, landscapePosLeft, portraitPosTop, endRotation)
+ component,
+ landscapePosLeft,
+ portraitPosTop,
+ endRotation
+ )
}
}
}
@@ -257,45 +244,46 @@ fun LayerTraceEntrySubject.splitAppLayerBoundsSnapToDivider(
val displayBounds = WindowUtils.getDisplayBounds(rotation)
return invoke {
val dividerRegion = layer(SPLIT_SCREEN_DIVIDER_COMPONENT).visibleRegion.region
- visibleRegion(component).coversAtMost(
- if (displayBounds.width > displayBounds.height) {
- if (landscapePosLeft) {
- Region.from(
- 0,
- 0,
- (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2,
- displayBounds.bounds.bottom)
- } else {
- Region.from(
- (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2,
- 0,
- displayBounds.bounds.right,
- displayBounds.bounds.bottom
- )
- }
- } else {
- if (portraitPosTop) {
- Region.from(
- 0,
- 0,
- displayBounds.bounds.right,
- (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2)
+ visibleRegion(component)
+ .coversAtMost(
+ if (displayBounds.width > displayBounds.height) {
+ if (landscapePosLeft) {
+ Region.from(
+ 0,
+ 0,
+ (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2,
+ displayBounds.bounds.bottom
+ )
+ } else {
+ Region.from(
+ (dividerRegion.bounds.left + dividerRegion.bounds.right) / 2,
+ 0,
+ displayBounds.bounds.right,
+ displayBounds.bounds.bottom
+ )
+ }
} else {
- Region.from(
- 0,
- (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2,
- displayBounds.bounds.right,
- displayBounds.bounds.bottom
- )
+ if (portraitPosTop) {
+ Region.from(
+ 0,
+ 0,
+ displayBounds.bounds.right,
+ (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2
+ )
+ } else {
+ Region.from(
+ 0,
+ (dividerRegion.bounds.top + dividerRegion.bounds.bottom) / 2,
+ displayBounds.bounds.right,
+ displayBounds.bounds.bottom
+ )
+ }
}
- }
- )
+ )
}
}
-fun FlickerTestParameter.appWindowBecomesVisible(
- component: IComponentMatcher
-) {
+fun FlickerTestParameter.appWindowBecomesVisible(component: IComponentMatcher) {
assertWm {
this.isAppWindowInvisible(component)
.then()
@@ -307,60 +295,32 @@ fun FlickerTestParameter.appWindowBecomesVisible(
}
}
-fun FlickerTestParameter.appWindowBecomesInvisible(
- component: IComponentMatcher
-) {
- assertWm {
- this.isAppWindowVisible(component)
- .then()
- .isAppWindowInvisible(component)
- }
+fun FlickerTestParameter.appWindowBecomesInvisible(component: IComponentMatcher) {
+ assertWm { this.isAppWindowVisible(component).then().isAppWindowInvisible(component) }
}
-fun FlickerTestParameter.appWindowIsVisibleAtStart(
- component: IComponentMatcher
-) {
- assertWmStart {
- this.isAppWindowVisible(component)
- }
+fun FlickerTestParameter.appWindowIsVisibleAtStart(component: IComponentMatcher) {
+ assertWmStart { this.isAppWindowVisible(component) }
}
-fun FlickerTestParameter.appWindowIsVisibleAtEnd(
- component: IComponentMatcher
-) {
- assertWmEnd {
- this.isAppWindowVisible(component)
- }
+fun FlickerTestParameter.appWindowIsVisibleAtEnd(component: IComponentMatcher) {
+ assertWmEnd { this.isAppWindowVisible(component) }
}
-fun FlickerTestParameter.appWindowIsInvisibleAtStart(
- component: IComponentMatcher
-) {
- assertWmStart {
- this.isAppWindowInvisible(component)
- }
+fun FlickerTestParameter.appWindowIsInvisibleAtStart(component: IComponentMatcher) {
+ assertWmStart { this.isAppWindowInvisible(component) }
}
-fun FlickerTestParameter.appWindowIsInvisibleAtEnd(
- component: IComponentMatcher
-) {
- assertWmEnd {
- this.isAppWindowInvisible(component)
- }
+fun FlickerTestParameter.appWindowIsInvisibleAtEnd(component: IComponentMatcher) {
+ assertWmEnd { this.isAppWindowInvisible(component) }
}
-fun FlickerTestParameter.appWindowKeepVisible(
- component: IComponentMatcher
-) {
- assertWm {
- this.isAppWindowVisible(component)
- }
+fun FlickerTestParameter.appWindowKeepVisible(component: IComponentMatcher) {
+ assertWm { this.isAppWindowVisible(component) }
}
fun FlickerTestParameter.dockedStackDividerIsVisibleAtEnd() {
- assertLayersEnd {
- this.isVisible(DOCKED_STACK_DIVIDER_COMPONENT)
- }
+ assertLayersEnd { this.isVisible(DOCKED_STACK_DIVIDER_COMPONENT) }
}
fun FlickerTestParameter.dockedStackDividerBecomesVisible() {
@@ -380,9 +340,7 @@ fun FlickerTestParameter.dockedStackDividerBecomesInvisible() {
}
fun FlickerTestParameter.dockedStackDividerNotExistsAtEnd() {
- assertLayersEnd {
- this.notContains(DOCKED_STACK_DIVIDER_COMPONENT)
- }
+ assertLayersEnd { this.notContains(DOCKED_STACK_DIVIDER_COMPONENT) }
}
fun FlickerTestParameter.appPairsPrimaryBoundsIsVisibleAtEnd(
@@ -391,8 +349,7 @@ fun FlickerTestParameter.appPairsPrimaryBoundsIsVisibleAtEnd(
) {
assertLayersEnd {
val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
- visibleRegion(primaryComponent)
- .overlaps(getPrimaryRegion(dividerRegion, rotation))
+ visibleRegion(primaryComponent).overlaps(getPrimaryRegion(dividerRegion, rotation))
}
}
@@ -402,8 +359,7 @@ fun FlickerTestParameter.dockedStackPrimaryBoundsIsVisibleAtEnd(
) {
assertLayersEnd {
val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
- visibleRegion(primaryComponent)
- .overlaps(getPrimaryRegion(dividerRegion, rotation))
+ visibleRegion(primaryComponent).overlaps(getPrimaryRegion(dividerRegion, rotation))
}
}
@@ -413,8 +369,7 @@ fun FlickerTestParameter.appPairsSecondaryBoundsIsVisibleAtEnd(
) {
assertLayersEnd {
val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
- visibleRegion(secondaryComponent)
- .overlaps(getSecondaryRegion(dividerRegion, rotation))
+ visibleRegion(secondaryComponent).overlaps(getSecondaryRegion(dividerRegion, rotation))
}
}
@@ -424,8 +379,7 @@ fun FlickerTestParameter.dockedStackSecondaryBoundsIsVisibleAtEnd(
) {
assertLayersEnd {
val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
- visibleRegion(secondaryComponent)
- .overlaps(getSecondaryRegion(dividerRegion, rotation))
+ visibleRegion(secondaryComponent).overlaps(getSecondaryRegion(dividerRegion, rotation))
}
}
@@ -433,12 +387,16 @@ fun getPrimaryRegion(dividerRegion: Region, rotation: Int): Region {
val displayBounds = WindowUtils.getDisplayBounds(rotation)
return if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
Region.from(
- 0, 0, displayBounds.bounds.right,
+ 0,
+ 0,
+ displayBounds.bounds.right,
dividerRegion.bounds.top + WindowUtils.dockedStackDividerInset
)
} else {
Region.from(
- 0, 0, dividerRegion.bounds.left + WindowUtils.dockedStackDividerInset,
+ 0,
+ 0,
+ dividerRegion.bounds.left + WindowUtils.dockedStackDividerInset,
displayBounds.bounds.bottom
)
}
@@ -448,13 +406,17 @@ fun getSecondaryRegion(dividerRegion: Region, rotation: Int): Region {
val displayBounds = WindowUtils.getDisplayBounds(rotation)
return if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
Region.from(
- 0, dividerRegion.bounds.bottom - WindowUtils.dockedStackDividerInset,
- displayBounds.bounds.right, displayBounds.bounds.bottom
+ 0,
+ dividerRegion.bounds.bottom - WindowUtils.dockedStackDividerInset,
+ displayBounds.bounds.right,
+ displayBounds.bounds.bottom
)
} else {
Region.from(
- dividerRegion.bounds.right - WindowUtils.dockedStackDividerInset, 0,
- displayBounds.bounds.right, displayBounds.bounds.bottom
+ dividerRegion.bounds.right - WindowUtils.dockedStackDividerInset,
+ 0,
+ displayBounds.bounds.right,
+ displayBounds.bounds.bottom
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
index 53dd8b04afeb..79978929cf3e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonConstants.kt
@@ -15,6 +15,7 @@
*/
@file:JvmName("CommonConstants")
+
package com.android.wm.shell.flicker
import com.android.server.wm.traces.common.ComponentNameMatcher
@@ -26,5 +27,8 @@ val SPLIT_SCREEN_DIVIDER_COMPONENT = ComponentNameMatcher("", "StageCoordinatorS
val SPLIT_DECOR_MANAGER = ComponentNameMatcher("", "SplitDecorManager#")
enum class Direction {
- UP, DOWN, LEFT, RIGHT
+ UP,
+ DOWN,
+ LEFT,
+ RIGHT
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/MultiWindowUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/MultiWindowUtils.kt
index c045325f19c3..87b94ff8668b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/MultiWindowUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/MultiWindowUtils.kt
@@ -33,17 +33,23 @@ object MultiWindowUtils {
}
fun getDevEnableNonResizableMultiWindow(context: Context): Int =
- Settings.Global.getInt(context.contentResolver,
- Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW)
+ Settings.Global.getInt(
+ context.contentResolver,
+ Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW
+ )
fun setDevEnableNonResizableMultiWindow(context: Context, configValue: Int) =
- Settings.Global.putInt(context.contentResolver,
- Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW, configValue)
+ Settings.Global.putInt(
+ context.contentResolver,
+ Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW,
+ configValue
+ )
fun setSupportsNonResizableMultiWindow(instrumentation: Instrumentation, configValue: Int) =
executeShellCommand(
instrumentation,
- createConfigSupportsNonResizableMultiWindowCommand(configValue))
+ createConfigSupportsNonResizableMultiWindowCommand(configValue)
+ )
fun resetMultiWindowConfig(instrumentation: Instrumentation) =
executeShellCommand(instrumentation, resetMultiWindowConfigCommand)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NotificationListener.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NotificationListener.kt
index 51f7a18f60dd..e0ef92457f58 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NotificationListener.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NotificationListener.kt
@@ -51,7 +51,7 @@ class NotificationListener : NotificationListenerService() {
private const val CMD_NOTIFICATION_ALLOW_LISTENER = "cmd notification allow_listener %s"
private const val CMD_NOTIFICATION_DISALLOW_LISTENER =
- "cmd notification disallow_listener %s"
+ "cmd notification disallow_listener %s"
private const val COMPONENT_NAME = "com.android.wm.shell.flicker/.NotificationListener"
private var instance: NotificationListener? = null
@@ -79,25 +79,23 @@ class NotificationListener : NotificationListenerService() {
): StatusBarNotification? {
instance?.run {
return notifications.values.firstOrNull(predicate)
- } ?: throw IllegalStateException("NotificationListenerService is not connected")
+ }
+ ?: throw IllegalStateException("NotificationListenerService is not connected")
}
fun waitForNotificationToAppear(
predicate: (StatusBarNotification) -> Boolean
): StatusBarNotification? {
instance?.let {
- return waitForResult(extractor = {
- it.notifications.values.firstOrNull(predicate)
- }).second
- } ?: throw IllegalStateException("NotificationListenerService is not connected")
+ return waitForResult(extractor = { it.notifications.values.firstOrNull(predicate) })
+ .second
+ }
+ ?: throw IllegalStateException("NotificationListenerService is not connected")
}
- fun waitForNotificationToDisappear(
- predicate: (StatusBarNotification) -> Boolean
- ): Boolean {
- return instance?.let {
- wait { it.notifications.values.none(predicate) }
- } ?: throw IllegalStateException("NotificationListenerService is not connected")
+ fun waitForNotificationToDisappear(predicate: (StatusBarNotification) -> Boolean): Boolean {
+ return instance?.let { wait { it.notifications.values.none(predicate) } }
+ ?: throw IllegalStateException("NotificationListenerService is not connected")
}
}
-} \ No newline at end of file
+}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt
index 4d87ec9e872f..556cb06f3ca1 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt
@@ -15,6 +15,7 @@
*/
@file:JvmName("WaitUtils")
+
package com.android.wm.shell.flicker
import android.os.SystemClock
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt
index cbe085be8952..0fc2004ce7f9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/BaseBubbleScreen.kt
@@ -34,21 +34,21 @@ import com.android.server.wm.flicker.helpers.SYSTEMUI_PACKAGE
import com.android.wm.shell.flicker.BaseTest
import org.junit.runners.Parameterized
-/**
- * Base configurations for Bubble flicker tests
- */
-abstract class BaseBubbleScreen(
- testSpec: FlickerTestParameter
-) : BaseTest(testSpec) {
+/** Base configurations for Bubble flicker tests */
+abstract class BaseBubbleScreen(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
protected val context: Context = instrumentation.context
protected val testApp = LaunchBubbleHelper(instrumentation)
- private val notifyManager = INotificationManager.Stub.asInterface(
- ServiceManager.getService(Context.NOTIFICATION_SERVICE))
+ private val notifyManager =
+ INotificationManager.Stub.asInterface(
+ ServiceManager.getService(Context.NOTIFICATION_SERVICE)
+ )
- private val uid = context.packageManager.getApplicationInfo(
- testApp.`package`, PackageManager.ApplicationInfoFlags.of(0)).uid
+ private val uid =
+ context.packageManager
+ .getApplicationInfo(testApp.`package`, PackageManager.ApplicationInfoFlags.of(0))
+ .uid
@JvmOverloads
protected open fun buildTransition(
@@ -56,16 +56,22 @@ abstract class BaseBubbleScreen(
): FlickerBuilder.() -> Unit {
return {
setup {
- notifyManager.setBubblesAllowed(testApp.`package`,
- uid, NotificationManager.BUBBLE_PREFERENCE_ALL)
+ notifyManager.setBubblesAllowed(
+ testApp.`package`,
+ uid,
+ NotificationManager.BUBBLE_PREFERENCE_ALL
+ )
testApp.launchViaIntent(wmHelper)
waitAndGetAddBubbleBtn()
waitAndGetCancelAllBtn()
}
teardown {
- notifyManager.setBubblesAllowed(testApp.`package`,
- uid, NotificationManager.BUBBLE_PREFERENCE_NONE)
+ notifyManager.setBubblesAllowed(
+ testApp.`package`,
+ uid,
+ NotificationManager.BUBBLE_PREFERENCE_NONE
+ )
testApp.exit()
}
@@ -73,17 +79,17 @@ abstract class BaseBubbleScreen(
}
}
- protected fun Flicker.waitAndGetAddBubbleBtn(): UiObject2? = device.wait(Until.findObject(
- By.text("Add Bubble")), FIND_OBJECT_TIMEOUT)
- protected fun Flicker.waitAndGetCancelAllBtn(): UiObject2? = device.wait(Until.findObject(
- By.text("Cancel All Bubble")), FIND_OBJECT_TIMEOUT)
+ protected fun Flicker.waitAndGetAddBubbleBtn(): UiObject2? =
+ device.wait(Until.findObject(By.text("Add Bubble")), FIND_OBJECT_TIMEOUT)
+ protected fun Flicker.waitAndGetCancelAllBtn(): UiObject2? =
+ device.wait(Until.findObject(By.text("Cancel All Bubble")), FIND_OBJECT_TIMEOUT)
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0))
+ .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0))
}
const val FIND_OBJECT_TIMEOUT = 2000L
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
index 4a914a3eaf5c..ab721173763e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/DismissBubbleScreen.kt
@@ -38,7 +38,9 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:DismissBubbleScreen`
*
* Actions:
+ * ```
* Dismiss a bubble notification
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -58,11 +60,11 @@ open class DismissBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScree
transitions {
wm.run { wm.defaultDisplay.getMetrics(displaySize) }
val dist = Point((displaySize.widthPixels / 2), displaySize.heightPixels)
- val showBubble = device.wait(
- Until.findObject(
- By.res(SYSTEM_UI_PACKAGE, BUBBLE_RES_NAME)
- ), FIND_OBJECT_TIMEOUT
- )
+ val showBubble =
+ device.wait(
+ Until.findObject(By.res(SYSTEM_UI_PACKAGE, BUBBLE_RES_NAME)),
+ FIND_OBJECT_TIMEOUT
+ )
showBubble?.run { drag(dist, 1000) } ?: error("Show bubble not found")
}
}
@@ -70,22 +72,18 @@ open class DismissBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScree
@Presubmit
@Test
open fun testAppIsAlwaysVisible() {
- testSpec.assertLayers {
- this.isVisible(testApp)
- }
+ testSpec.assertLayers { this.isVisible(testApp) }
}
/** {@inheritDoc} */
@Postsubmit
@Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() =
- super.taskBarLayerIsVisibleAtStartAndEnd()
+ override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
@Postsubmit
@Test
- override fun taskBarWindowIsAlwaysVisible() =
- super.taskBarWindowIsAlwaysVisible()
+ override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
@Postsubmit
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
index d48175e5f49a..226eab89920f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/ExpandBubbleScreen.kt
@@ -33,9 +33,11 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:ExpandBubbleScreen`
*
* Actions:
+ * ```
* Launch an app and enable app's bubble notification
* Send a bubble notification
* The activity for the bubble is launched
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -50,11 +52,11 @@ open class ExpandBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen
addBubbleBtn?.click() ?: error("Add Bubble not found")
}
transitions {
- val showBubble = device.wait(
- Until.findObject(
- By.res("com.android.systemui", "bubble_view")
- ), FIND_OBJECT_TIMEOUT
- )
+ val showBubble =
+ device.wait(
+ Until.findObject(By.res("com.android.systemui", "bubble_view")),
+ FIND_OBJECT_TIMEOUT
+ )
showBubble?.run { showBubble.click() } ?: error("Bubble notify not found")
}
}
@@ -62,8 +64,6 @@ open class ExpandBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen
@Presubmit
@Test
open fun testAppIsAlwaysVisible() {
- testSpec.assertLayers {
- this.isVisible(testApp)
- }
+ testSpec.assertLayers { this.isVisible(testApp) }
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
index 83dcb5a3fb8b..275f6c802293 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleFromLockScreen.kt
@@ -36,7 +36,9 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:LaunchBubbleFromLockScreen`
*
* Actions:
+ * ```
* Launch an bubble from notification on lock screen
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -50,36 +52,32 @@ class LaunchBubbleFromLockScreen(testSpec: FlickerTestParameter) : BaseBubbleScr
val addBubbleBtn = waitAndGetAddBubbleBtn()
addBubbleBtn?.click() ?: error("Bubble widget not found")
device.sleep()
- wmHelper.StateSyncBuilder()
- .withoutTopVisibleAppWindows()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
device.wakeUp()
}
transitions {
// Swipe & wait for the notification shade to expand so all can be seen
- val wm = context.getSystemService(WindowManager::class.java)
- ?: error("Unable to obtain WM service")
+ val wm =
+ context.getSystemService(WindowManager::class.java)
+ ?: error("Unable to obtain WM service")
val metricInsets = wm.currentWindowMetrics.windowInsets
- val insets = metricInsets.getInsetsIgnoringVisibility(
- WindowInsets.Type.statusBars()
- or WindowInsets.Type.displayCutout()
- )
+ val insets =
+ metricInsets.getInsetsIgnoringVisibility(
+ WindowInsets.Type.statusBars() or WindowInsets.Type.displayCutout()
+ )
device.swipe(100, insets.top + 100, 100, device.displayHeight / 2, 4)
device.waitForIdle(2000)
instrumentation.uiAutomation.syncInputTransactions()
- val notification = device.wait(
- Until.findObject(
- By.text("BubbleChat")
- ), FIND_OBJECT_TIMEOUT
- )
+ val notification =
+ device.wait(Until.findObject(By.text("BubbleChat")), FIND_OBJECT_TIMEOUT)
notification?.click() ?: error("Notification not found")
instrumentation.uiAutomation.syncInputTransactions()
- val showBubble = device.wait(
- Until.findObject(
- By.res("com.android.systemui", "bubble_view")
- ), FIND_OBJECT_TIMEOUT
- )
+ val showBubble =
+ device.wait(
+ Until.findObject(By.res("com.android.systemui", "bubble_view")),
+ FIND_OBJECT_TIMEOUT
+ )
showBubble?.click() ?: error("Bubble notify not found")
instrumentation.uiAutomation.syncInputTransactions()
val cancelAllBtn = waitAndGetCancelAllBtn()
@@ -90,9 +88,7 @@ class LaunchBubbleFromLockScreen(testSpec: FlickerTestParameter) : BaseBubbleScr
@FlakyTest(bugId = 242088970)
@Test
fun testAppIsVisibleAtEnd() {
- testSpec.assertLayersEnd {
- this.isVisible(testApp)
- }
+ testSpec.assertLayersEnd { this.isVisible(testApp) }
}
/** {@inheritDoc} */
@@ -104,32 +100,27 @@ class LaunchBubbleFromLockScreen(testSpec: FlickerTestParameter) : BaseBubbleScr
/** {@inheritDoc} */
@FlakyTest(bugId = 206753786)
@Test
- override fun navBarLayerIsVisibleAtStartAndEnd() =
- super.navBarLayerIsVisibleAtStartAndEnd()
+ override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
@FlakyTest(bugId = 206753786)
@Test
- override fun navBarLayerPositionAtStartAndEnd() =
- super.navBarLayerPositionAtStartAndEnd()
+ override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
@FlakyTest(bugId = 206753786)
@Test
- override fun navBarWindowIsAlwaysVisible() =
- super.navBarWindowIsAlwaysVisible()
+ override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
@FlakyTest(bugId = 242088970)
@Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() =
- super.taskBarLayerIsVisibleAtStartAndEnd()
+ override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
@Postsubmit
@Test
- override fun taskBarWindowIsAlwaysVisible() =
- super.taskBarWindowIsAlwaysVisible()
+ override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
@FlakyTest(bugId = 242088970)
@@ -140,14 +131,12 @@ class LaunchBubbleFromLockScreen(testSpec: FlickerTestParameter) : BaseBubbleScr
/** {@inheritDoc} */
@FlakyTest(bugId = 242088970)
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
@FlakyTest(bugId = 242088970)
@Test
- override fun statusBarWindowIsAlwaysVisible() =
- super.statusBarWindowIsAlwaysVisible()
+ override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
@FlakyTest(bugId = 242088970)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
index 81204f49d03b..b86599913649 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/LaunchBubbleScreen.kt
@@ -32,8 +32,10 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:LaunchBubbleScreen`
*
* Actions:
+ * ```
* Launch an app and enable app's bubble notification
* Send a bubble notification
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -48,17 +50,15 @@ open class LaunchBubbleScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen
addBubbleBtn?.click() ?: error("Bubble widget not found")
device.wait(
- Until.findObjects(
- By.res(SYSTEM_UI_PACKAGE, BUBBLE_RES_NAME)
- ), FIND_OBJECT_TIMEOUT
- ) ?: error("No bubbles found")
+ Until.findObjects(By.res(SYSTEM_UI_PACKAGE, BUBBLE_RES_NAME)),
+ FIND_OBJECT_TIMEOUT
+ )
+ ?: error("No bubbles found")
}
}
@Test
open fun testAppIsAlwaysVisible() {
- testSpec.assertLayers {
- this.isVisible(testApp)
- }
+ testSpec.assertLayers { this.isVisible(testApp) }
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt
index 364090510138..bf4d7d4e7734 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreen.kt
@@ -38,7 +38,9 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:MultiBubblesScreen`
*
* Actions:
+ * ```
* Switch in different bubble notifications
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -59,20 +61,22 @@ open class MultiBubblesScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen
addBubbleBtn.click()
SystemClock.sleep(1000)
}
- val showBubble = device.wait(
- Until.findObject(
- By.res(SYSTEM_UI_PACKAGE, BUBBLE_RES_NAME)
- ), FIND_OBJECT_TIMEOUT
- ) ?: error("Show bubble not found")
+ val showBubble =
+ device.wait(
+ Until.findObject(By.res(SYSTEM_UI_PACKAGE, BUBBLE_RES_NAME)),
+ FIND_OBJECT_TIMEOUT
+ )
+ ?: error("Show bubble not found")
showBubble.click()
SystemClock.sleep(1000)
}
transitions {
- val bubbles: List<UiObject2> = device.wait(
- Until.findObjects(
- By.res(SYSTEM_UI_PACKAGE, BUBBLE_RES_NAME)
- ), FIND_OBJECT_TIMEOUT
- ) ?: error("No bubbles found")
+ val bubbles: List<UiObject2> =
+ device.wait(
+ Until.findObjects(By.res(SYSTEM_UI_PACKAGE, BUBBLE_RES_NAME)),
+ FIND_OBJECT_TIMEOUT
+ )
+ ?: error("No bubbles found")
for (entry in bubbles) {
entry.click()
SystemClock.sleep(1000)
@@ -83,8 +87,6 @@ open class MultiBubblesScreen(testSpec: FlickerTestParameter) : BaseBubbleScreen
@Presubmit
@Test
open fun testAppIsAlwaysVisible() {
- testSpec.assertLayers {
- this.isVisible(testApp)
- }
+ testSpec.assertLayers { this.isVisible(testApp) }
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenShellTransit.kt
index 839fef904244..57adeab7b070 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/bubble/MultiBubblesScreenShellTransit.kt
@@ -30,9 +30,8 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FlakyTest(bugId = 217777115)
-class MultiBubblesScreenShellTransit(
- testSpec: FlickerTestParameter
-) : MultiBubblesScreen(testSpec) {
+class MultiBubblesScreenShellTransit(testSpec: FlickerTestParameter) :
+ MultiBubblesScreen(testSpec) {
@Before
override fun before() {
Assume.assumeTrue(isShellTransitionsEnabled)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
index 1be93527e0e5..1fc0375e9feb 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/AutoEnterPipOnGoToHomeTest.kt
@@ -40,16 +40,19 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:AutoEnterPipOnGoToHomeTest`
*
* Actions:
+ * ```
* Launch an app in full screen
* Select "Auto-enter PiP" radio button
* Press Home button or swipe up to go Home and put [pipApp] in pip mode
- *
+ * ```
* Notes:
+ * ```
* 1. All assertions are inherited from [EnterPipTest]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -57,9 +60,7 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@FlakyTest(bugId = 238367575)
class AutoEnterPipOnGoToHomeTest(testSpec: FlickerTestParameter) : EnterPipTest(testSpec) {
- /**
- * Defines the transition used to run the test
- */
+ /** Defines the transition used to run the test */
override val transition: FlickerBuilder.() -> Unit
get() = {
setup {
@@ -76,9 +77,7 @@ class AutoEnterPipOnGoToHomeTest(testSpec: FlickerTestParameter) : EnterPipTest(
RemoveAllTasksButHomeRule.removeAllTasksButHome()
pipApp.exit(wmHelper)
}
- transitions {
- tapl.goHome()
- }
+ transitions { tapl.goHome() }
}
@FlakyTest
@@ -92,9 +91,7 @@ class AutoEnterPipOnGoToHomeTest(testSpec: FlickerTestParameter) : EnterPipTest(
}
}
- /**
- * Checks that [pipApp] window is animated towards default position in right bottom corner
- */
+ /** Checks that [pipApp] window is animated towards default position in right bottom corner */
@Presubmit
@Test
fun pipLayerMovesTowardsRightBottomCorner() {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
index 75543cfed1ac..c8aa6d20c91b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipOnUserLeaveHintTest.kt
@@ -16,14 +16,12 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.dsl.FlickerBuilder
-import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.rules.RemoveAllTasksButHomeRule
@@ -40,25 +38,26 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:EnterPipOnUserLeaveHintTest`
*
* Actions:
+ * ```
* Launch an app in full screen
* Select "Via code behind" radio button
* Press Home button or swipe up to go Home and put [pipApp] in pip mode
- *
+ * ```
* Notes:
+ * ```
* 1. All assertions are inherited from [EnterPipTest]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class EnterPipOnUserLeaveHintTest(testSpec: FlickerTestParameter) : EnterPipTest(testSpec) {
- /**
- * Defines the transition used to run the test
- */
+ /** Defines the transition used to run the test */
override val transition: FlickerBuilder.() -> Unit
get() = {
setup {
@@ -73,20 +72,17 @@ class EnterPipOnUserLeaveHintTest(testSpec: FlickerTestParameter) : EnterPipTest
RemoveAllTasksButHomeRule.removeAllTasksButHome()
pipApp.exit(wmHelper)
}
- transitions {
- tapl.goHome()
- }
+ transitions { tapl.goHome() }
}
@Presubmit
@Test
override fun pipAppLayerAlwaysVisible() {
- if (!testSpec.isGesturalNavigation) super.pipAppLayerAlwaysVisible() else {
+ if (!testSpec.isGesturalNavigation) super.pipAppLayerAlwaysVisible()
+ else {
// pip layer in gesture nav will disappear during transition
testSpec.assertLayers {
- this.isVisible(pipApp)
- .then().isInvisible(pipApp)
- .then().isVisible(pipApp)
+ this.isVisible(pipApp).then().isInvisible(pipApp).then().isVisible(pipApp)
}
}
}
@@ -110,28 +106,17 @@ class EnterPipOnUserLeaveHintTest(testSpec: FlickerTestParameter) : EnterPipTest
@Presubmit
@Test
override fun entireScreenCovered() {
- Assume.assumeFalse(isShellTransitionsEnabled)
- super.entireScreenCovered()
- }
-
- @FlakyTest(bugId = 227313015)
- @Test
- fun entireScreenCovered_ShellTransit() {
- Assume.assumeTrue(isShellTransitionsEnabled)
super.entireScreenCovered()
}
@Presubmit
@Test
override fun pipLayerRemainInsideVisibleBounds() {
- if (!testSpec.isGesturalNavigation) super.pipLayerRemainInsideVisibleBounds() else {
+ if (!testSpec.isGesturalNavigation) super.pipLayerRemainInsideVisibleBounds()
+ else {
// pip layer in gesture nav will disappear during transition
- testSpec.assertLayersStart {
- this.visibleRegion(pipApp).coversAtMost(displayBounds)
- }
- testSpec.assertLayersEnd {
- this.visibleRegion(pipApp).coversAtMost(displayBounds)
- }
+ testSpec.assertLayersStart { this.visibleRegion(pipApp).coversAtMost(displayBounds) }
+ testSpec.assertLayersEnd { this.visibleRegion(pipApp).coversAtMost(displayBounds) }
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
index 239d337be991..2b629e73e750 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipTest.kt
@@ -16,7 +16,6 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -40,16 +39,19 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:EnterPipTest`
*
* Actions:
+ * ```
* Launch an app in full screen
* Press an "enter pip" button to put [pipApp] in pip mode
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited from [PipTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -57,7 +59,7 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
- /** {@inheritDoc} */
+ /** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit
get() = {
setup {
@@ -70,31 +72,23 @@ open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec
RemoveAllTasksButHomeRule.removeAllTasksButHome()
pipApp.exit(wmHelper)
}
- transitions {
- pipApp.clickEnterPipButton(wmHelper)
- }
+ transitions { pipApp.clickEnterPipButton(wmHelper) }
}
- /**
- * Checks [pipApp] window remains visible throughout the animation
- */
+ /** Checks [pipApp] window remains visible throughout the animation */
@Presubmit
@Test
open fun pipAppWindowAlwaysVisible() {
- testSpec.assertWm {
- this.isAppWindowVisible(pipApp)
- }
+ testSpec.assertWm { this.isAppWindowVisible(pipApp) }
}
/**
* Checks [pipApp] layer remains visible throughout the animation
*/
- @FlakyTest(bugId = 239807171)
+ @Presubmit
@Test
open fun pipAppLayerAlwaysVisible() {
- testSpec.assertLayers {
- this.isVisible(pipApp)
- }
+ testSpec.assertLayers { this.isVisible(pipApp) }
}
/**
@@ -104,26 +98,20 @@ open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec
@Presubmit
@Test
fun pipWindowRemainInsideVisibleBounds() {
- testSpec.assertWmVisibleRegion(pipApp) {
- coversAtMost(displayBounds)
- }
+ testSpec.assertWmVisibleRegion(pipApp) { coversAtMost(displayBounds) }
}
/**
* Checks that the pip app layer remains inside the display bounds throughout the whole
* animation
*/
- @FlakyTest(bugId = 239807171)
+ @Presubmit
@Test
open fun pipLayerRemainInsideVisibleBounds() {
- testSpec.assertLayersVisibleRegion(pipApp) {
- coversAtMost(displayBounds)
- }
+ testSpec.assertLayersVisibleRegion(pipApp) { coversAtMost(displayBounds) }
}
- /**
- * Checks that the visible region of [pipApp] always reduces during the animation
- */
+ /** Checks that the visible region of [pipApp] always reduces during the animation */
@Presubmit
@Test
open fun pipLayerReduces() {
@@ -135,9 +123,7 @@ open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec
}
}
- /**
- * Checks that [pipApp] window becomes pinned
- */
+ /** Checks that [pipApp] window becomes pinned */
@Presubmit
@Test
fun pipWindowBecomesPinned() {
@@ -148,9 +134,7 @@ open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec
}
}
- /**
- * Checks [ComponentMatcher.LAUNCHER] layer remains visible throughout the animation
- */
+ /** Checks [ComponentMatcher.LAUNCHER] layer remains visible throughout the animation */
@Presubmit
@Test
fun launcherLayerBecomesVisible() {
@@ -162,31 +146,27 @@ open class EnterPipTest(testSpec: FlickerTestParameter) : PipTransition(testSpec
}
/**
- * Checks that the focus changes between the [pipApp] window and the launcher when
- * closing the pip window
+ * Checks that the focus changes between the [pipApp] window and the launcher when closing the
+ * pip window
*/
@Presubmit
@Test
open fun focusChanges() {
- testSpec.assertEventLog {
- this.focusChanges(pipApp.`package`, "NexusLauncherActivity")
- }
+ testSpec.assertEventLog { this.focusChanges(pipApp.`package`, "NexusLauncherActivity") }
}
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(
- supportedRotations = listOf(Surface.ROTATION_0)
- )
+ .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0))
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
index 11bc1f7ea406..104b409731dd 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/EnterPipToOtherOrientationTest.kt
@@ -18,7 +18,6 @@ package com.android.wm.shell.flicker.pip
import android.app.Activity
import android.platform.test.annotations.FlakyTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
@@ -225,7 +224,7 @@ class EnterPipToOtherOrientationTest(
}
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
index 628599160c65..3d8525b3d4ad 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipToAppTransition.kt
@@ -21,9 +21,7 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.helpers.FixedOrientationAppHelper
import org.junit.Test
-/**
- * Base class for pip expand tests
- */
+/** Base class for pip expand tests */
abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
protected val testApp = FixedOrientationAppHelper(instrumentation)
@@ -34,9 +32,7 @@ abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTrans
@Presubmit
@Test
open fun pipAppWindowRemainInsideVisibleBounds() {
- testSpec.assertWmVisibleRegion(pipApp) {
- coversAtMost(displayBounds)
- }
+ testSpec.assertWmVisibleRegion(pipApp) { coversAtMost(displayBounds) }
}
/**
@@ -46,9 +42,7 @@ abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTrans
@Presubmit
@Test
open fun pipAppLayerRemainInsideVisibleBounds() {
- testSpec.assertLayersVisibleRegion(pipApp) {
- coversAtMost(displayBounds)
- }
+ testSpec.assertLayersVisibleRegion(pipApp) { coversAtMost(displayBounds) }
}
/**
@@ -78,44 +72,34 @@ abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTrans
@Test
open fun showBothAppLayersThenHidePip() {
testSpec.assertLayers {
- isVisible(testApp)
- .isVisible(pipApp)
- .then()
- .isInvisible(testApp)
- .isVisible(pipApp)
+ isVisible(testApp).isVisible(pipApp).then().isInvisible(testApp).isVisible(pipApp)
}
}
/**
- * Checks that the visible region of [testApp] plus the visible region of [pipApp]
- * cover the full display area at the start of the transition
+ * Checks that the visible region of [testApp] plus the visible region of [pipApp] cover the
+ * full display area at the start of the transition
*/
@Presubmit
@Test
open fun testPlusPipAppsCoverFullScreenAtStart() {
testSpec.assertLayersStart {
val pipRegion = visibleRegion(pipApp).region
- visibleRegion(testApp)
- .plus(pipRegion)
- .coversExactly(displayBounds)
+ visibleRegion(testApp).plus(pipRegion).coversExactly(displayBounds)
}
}
/**
- * Checks that the visible region oft [pipApp] covers the full display area at the end of
- * the transition
+ * Checks that the visible region oft [pipApp] covers the full display area at the end of the
+ * transition
*/
@Presubmit
@Test
open fun pipAppCoversFullScreenAtEnd() {
- testSpec.assertLayersEnd {
- visibleRegion(pipApp).coversExactly(displayBounds)
- }
+ testSpec.assertLayersEnd { visibleRegion(pipApp).coversExactly(displayBounds) }
}
- /**
- * Checks that the visible region of [pipApp] always expands during the animation
- */
+ /** Checks that the visible region of [pipApp] always expands during the animation */
@Presubmit
@Test
open fun pipLayerExpands() {
@@ -127,8 +111,6 @@ abstract class ExitPipToAppTransition(testSpec: FlickerTestParameter) : PipTrans
}
}
- /** {@inheritDoc} */
- @Presubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
+ /** {@inheritDoc} */
+ @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
index 39be89d2592b..3b8bb90988f9 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipTransition.kt
@@ -25,24 +25,18 @@ import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.LAUNCHER
import org.junit.Test
-/**
- * Base class for exiting pip (closing pip window) without returning to the app
- */
+/** Base class for exiting pip (closing pip window) without returning to the app */
abstract class ExitPipTransition(testSpec: FlickerTestParameter) : PipTransition(testSpec) {
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition {
- setup {
- this.setRotation(testSpec.startRotation)
- }
- teardown {
- this.setRotation(Surface.ROTATION_0)
- }
+ setup { this.setRotation(testSpec.startRotation) }
+ teardown { this.setRotation(Surface.ROTATION_0) }
}
/**
- * Checks that [pipApp] window is pinned and visible at the start and then becomes
- * unpinned and invisible at the same moment, and remains unpinned and invisible
- * until the end of the transition
+ * Checks that [pipApp] window is pinned and visible at the start and then becomes unpinned and
+ * invisible at the same moment, and remains unpinned and invisible until the end of the
+ * transition
*/
@Presubmit
@Test
@@ -53,30 +47,24 @@ abstract class ExitPipTransition(testSpec: FlickerTestParameter) : PipTransition
// and isAppWindowInvisible in the same assertion block.
testSpec.assertWm {
this.invoke("hasPipWindow") {
- it.isPinned(pipApp)
- .isAppWindowVisible(pipApp)
- .isAppWindowOnTop(pipApp)
- }.then().invoke("!hasPipWindow") {
- it.isNotPinned(pipApp)
- .isAppWindowNotOnTop(pipApp)
- }
+ it.isPinned(pipApp).isAppWindowVisible(pipApp).isAppWindowOnTop(pipApp)
+ }
+ .then()
+ .invoke("!hasPipWindow") { it.isNotPinned(pipApp).isAppWindowNotOnTop(pipApp) }
}
testSpec.assertWmEnd { isAppWindowInvisible(pipApp) }
} else {
testSpec.assertWm {
- this.invoke("hasPipWindow") {
- it.isPinned(pipApp).isAppWindowVisible(pipApp)
- }.then().invoke("!hasPipWindow") {
- it.isNotPinned(pipApp).isAppWindowInvisible(pipApp)
- }
+ this.invoke("hasPipWindow") { it.isPinned(pipApp).isAppWindowVisible(pipApp) }
+ .then()
+ .invoke("!hasPipWindow") { it.isNotPinned(pipApp).isAppWindowInvisible(pipApp) }
}
}
}
/**
- * Checks that [pipApp] and [LAUNCHER] layers are visible at the start
- * of the transition. Then [pipApp] layer becomes invisible, and remains invisible
- * until the end of the transition
+ * Checks that [pipApp] and [LAUNCHER] layers are visible at the start of the transition. Then
+ * [pipApp] layer becomes invisible, and remains invisible until the end of the transition
*/
@Presubmit
@Test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
index 8cb68facab08..5e3194ca4ee2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaExpandButtonClickTest.kt
@@ -16,7 +16,7 @@
package com.android.wm.shell.flicker.pip
-import android.platform.test.annotations.FlakyTest
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -76,12 +76,12 @@ class ExitPipViaExpandButtonClickTest(
}
/** {@inheritDoc} */
- @FlakyTest(bugId = 227313015)
+ @Presubmit
@Test
override fun entireScreenCovered() = super.entireScreenCovered()
/** {@inheritDoc} */
- @FlakyTest(bugId = 197726610)
+ @Presubmit
@Test
override fun pipLayerExpands() = super.pipLayerExpands()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
index 7ef332399246..3356d3e2ab2b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipViaIntentTest.kt
@@ -38,17 +38,20 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:ExitPipViaIntentTest`
*
* Actions:
+ * ```
* Launch an app in pip mode [pipApp],
* Launch another full screen mode [testApp]
* Expand [pipApp] app to full screen via an intent
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited from [PipTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -56,9 +59,7 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class ExitPipViaIntentTest(testSpec: FlickerTestParameter) : ExitPipToAppTransition(testSpec) {
- /**
- * Defines the transition used to run the test
- */
+ /** Defines the transition used to run the test */
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition {
setup {
@@ -69,18 +70,16 @@ class ExitPipViaIntentTest(testSpec: FlickerTestParameter) : ExitPipToAppTransit
// This will bring PipApp to fullscreen
pipApp.exitPipToFullScreenViaIntent(wmHelper)
// Wait until the other app is no longer visible
- wmHelper.StateSyncBuilder()
- .withWindowSurfaceDisappeared(testApp)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withWindowSurfaceDisappeared(testApp).waitForAndVerify()
}
}
/** {@inheritDoc} */
- @FlakyTest
+ @Presubmit
@Test
override fun entireScreenCovered() = super.entireScreenCovered()
- /** {@inheritDoc} */
+ /** {@inheritDoc} */
@Presubmit
@Test
override fun statusBarLayerPositionAtStartAndEnd() {
@@ -95,7 +94,7 @@ class ExitPipViaIntentTest(testSpec: FlickerTestParameter) : ExitPipToAppTransit
super.statusBarLayerPositionAtStartAndEnd()
}
- /** {@inheritDoc} */
+ /** {@inheritDoc} */
@FlakyTest(bugId = 197726610)
@Test
override fun pipLayerExpands() {
@@ -114,14 +113,14 @@ class ExitPipViaIntentTest(testSpec: FlickerTestParameter) : ExitPipToAppTransit
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
- supportedRotations = listOf(Surface.ROTATION_0))
+ return FlickerTestParameterFactory.getInstance()
+ .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0))
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
index a33d9144fbbb..d195abb2aaec 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithDismissButtonTest.kt
@@ -35,17 +35,20 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:ExitPipWithDismissButtonTest`
*
* Actions:
+ * ```
* Launch an app in pip mode [pipApp],
* Click on the pip window
* Click on dismiss button and wait window disappear
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [PipTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -56,9 +59,7 @@ class ExitPipWithDismissButtonTest(testSpec: FlickerTestParameter) : ExitPipTran
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
- transitions {
- pipApp.closePipWindow(wmHelper)
- }
+ transitions { pipApp.closePipWindow(wmHelper) }
}
/**
@@ -68,23 +69,21 @@ class ExitPipWithDismissButtonTest(testSpec: FlickerTestParameter) : ExitPipTran
@Presubmit
@Test
fun focusChanges() {
- testSpec.assertEventLog {
- this.focusChanges("PipMenuView", "NexusLauncherActivity")
- }
+ testSpec.assertEventLog { this.focusChanges("PipMenuView", "NexusLauncherActivity") }
}
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0))
+ .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0))
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
index e5695694dfbc..f7a244717141 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/ExitPipWithSwipeDownTest.kt
@@ -36,16 +36,19 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:ExitPipWithSwipeDownTest`
*
* Actions:
+ * ```
* Launch an app in pip mode [pipApp],
* Swipe the pip window to the bottom-center of the screen and wait it disappear
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [PipTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -60,20 +63,24 @@ class ExitPipWithSwipeDownTest(testSpec: FlickerTestParameter) : ExitPipTransiti
val pipCenterX = pipRegion.centerX()
val pipCenterY = pipRegion.centerY()
val displayCenterX = device.displayWidth / 2
- val barComponent = if (testSpec.isTablet) {
- ComponentNameMatcher.TASK_BAR
- } else {
- ComponentNameMatcher.NAV_BAR
- }
- val barLayerHeight = wmHelper.currentState.layerState
- .getLayerWithBuffer(barComponent)
- ?.visibleRegion
- ?.height ?: error("Couldn't find Nav or Task bar layer")
+ val barComponent =
+ if (testSpec.isTablet) {
+ ComponentNameMatcher.TASK_BAR
+ } else {
+ ComponentNameMatcher.NAV_BAR
+ }
+ val barLayerHeight =
+ wmHelper.currentState.layerState
+ .getLayerWithBuffer(barComponent)
+ ?.visibleRegion
+ ?.height
+ ?: error("Couldn't find Nav or Task bar layer")
// The dismiss button doesn't appear at the complete bottom of the screen,
val displayY = device.displayHeight - barLayerHeight
device.swipe(pipCenterX, pipCenterY, displayCenterX, displayY, 50)
// Wait until the other app is no longer visible
- wmHelper.StateSyncBuilder()
+ wmHelper
+ .StateSyncBuilder()
.withPipGone()
.withWindowSurfaceDisappeared(pipApp)
.withAppTransitionIdle()
@@ -81,29 +88,25 @@ class ExitPipWithSwipeDownTest(testSpec: FlickerTestParameter) : ExitPipTransiti
}
}
- /**
- * Checks that the focus doesn't change between windows during the transition
- */
+ /** Checks that the focus doesn't change between windows during the transition */
@Presubmit
@Test
fun focusDoesNotChange() {
- testSpec.assertEventLog {
- this.focusDoesNotChange()
- }
+ testSpec.assertEventLog { this.focusDoesNotChange() }
}
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0))
+ .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0))
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
index 5f9419694c13..b40106790b6c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/MovePipShelfHeightTransition.kt
@@ -23,34 +23,23 @@ import com.android.server.wm.flicker.traces.region.RegionSubject
import com.android.wm.shell.flicker.Direction
import org.junit.Test
-/**
- * Base class for pip tests with Launcher shelf height change
- */
-abstract class MovePipShelfHeightTransition(
- testSpec: FlickerTestParameter
-) : PipTransition(testSpec) {
+/** Base class for pip tests with Launcher shelf height change */
+abstract class MovePipShelfHeightTransition(testSpec: FlickerTestParameter) :
+ PipTransition(testSpec) {
protected val testApp = FixedOrientationAppHelper(instrumentation)
- /**
- * Checks [pipApp] window remains visible throughout the animation
- */
+ /** Checks [pipApp] window remains visible throughout the animation */
@Presubmit
@Test
open fun pipWindowIsAlwaysVisible() {
- testSpec.assertWm {
- isAppWindowVisible(pipApp)
- }
+ testSpec.assertWm { isAppWindowVisible(pipApp) }
}
- /**
- * Checks [pipApp] layer remains visible throughout the animation
- */
+ /** Checks [pipApp] layer remains visible throughout the animation */
@Presubmit
@Test
open fun pipLayerIsAlwaysVisible() {
- testSpec.assertLayers {
- isVisible(pipApp)
- }
+ testSpec.assertLayers { isVisible(pipApp) }
}
/**
@@ -60,9 +49,7 @@ abstract class MovePipShelfHeightTransition(
@Presubmit
@Test
open fun pipWindowRemainInsideVisibleBounds() {
- testSpec.assertWmVisibleRegion(pipApp) {
- coversAtMost(displayBounds)
- }
+ testSpec.assertWmVisibleRegion(pipApp) { coversAtMost(displayBounds) }
}
/**
@@ -72,9 +59,7 @@ abstract class MovePipShelfHeightTransition(
@Presubmit
@Test
open fun pipLayerRemainInsideVisibleBounds() {
- testSpec.assertLayersVisibleRegion(pipApp) {
- coversAtMost(displayBounds)
- }
+ testSpec.assertLayersVisibleRegion(pipApp) { coversAtMost(displayBounds) }
}
/**
@@ -83,9 +68,8 @@ abstract class MovePipShelfHeightTransition(
*/
protected fun pipWindowMoves(direction: Direction) {
testSpec.assertWm {
- val pipWindowFrameList = this.windowStates {
- pipApp.windowMatchesAnyOf(it) && it.isVisible
- }.map { it.frame }
+ val pipWindowFrameList =
+ this.windowStates { pipApp.windowMatchesAnyOf(it) && it.isVisible }.map { it.frame }
when (direction) {
Direction.UP -> assertRegionMovementUp(pipWindowFrameList)
Direction.DOWN -> assertRegionMovementDown(pipWindowFrameList)
@@ -100,9 +84,9 @@ abstract class MovePipShelfHeightTransition(
*/
protected fun pipLayerMoves(direction: Direction) {
testSpec.assertLayers {
- val pipLayerRegionList = this.layers {
- pipApp.layerMatchesAnyOf(it) && it.isVisible
- }.map { it.visibleRegion }
+ val pipLayerRegionList =
+ this.layers { pipApp.layerMatchesAnyOf(it) && it.isVisible }
+ .map { it.visibleRegion }
when (direction) {
Direction.UP -> assertRegionMovementUp(pipLayerRegionList)
Direction.DOWN -> assertRegionMovementDown(pipLayerRegionList)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
index ca086e850f52..3b64d218a73d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTest.kt
@@ -36,10 +36,7 @@ import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
-/**
- * Test Pip launch.
- * To run this test: `atest WMShellFlickerTests:PipKeyboardTest`
- */
+/** Test Pip launch. To run this test: `atest WMShellFlickerTests:PipKeyboardTest` */
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -52,7 +49,7 @@ open class PipKeyboardTest(testSpec: FlickerTestParameter) : PipTransition(testS
assumeFalse(isShellTransitionsEnabled)
}
- /** {@inheritDoc} */
+ /** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit
get() = buildTransition {
setup {
@@ -73,9 +70,7 @@ open class PipKeyboardTest(testSpec: FlickerTestParameter) : PipTransition(testS
}
}
- /**
- * Ensure the pip window remains visible throughout any keyboard interactions
- */
+ /** Ensure the pip window remains visible throughout any keyboard interactions */
@Presubmit
@Test
open fun pipInVisibleBounds() {
@@ -85,15 +80,11 @@ open class PipKeyboardTest(testSpec: FlickerTestParameter) : PipTransition(testS
}
}
- /**
- * Ensure that the pip window does not obscure the keyboard
- */
+ /** Ensure that the pip window does not obscure the keyboard */
@Presubmit
@Test
open fun pipIsAboveAppWindow() {
- testSpec.assertWmTag(TAG_IME_VISIBLE) {
- isAboveWindow(ComponentNameMatcher.IME, pipApp)
- }
+ testSpec.assertWmTag(TAG_IME_VISIBLE) { isAboveWindow(ComponentNameMatcher.IME, pipApp) }
}
companion object {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt
index 3b6d7da1eaa8..2a82c00bebd3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt
@@ -42,6 +42,5 @@ class PipKeyboardTestShellTransit(testSpec: FlickerTestParameter) : PipKeyboardT
@Presubmit
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
index 61cb2b0c0ca8..7de5494a7733 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest.kt
@@ -42,18 +42,21 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:PipRotationTest`
*
* Actions:
+ * ```
* Launch a [pipApp] in pip mode
* Launch another app [fixedApp] (appears below pip)
* Rotate the screen from [testSpec.startRotation] to [testSpec.endRotation]
* (usually, 0->90 and 90->0)
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited from [PipTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -75,43 +78,31 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS
testApp.launchViaIntent(wmHelper)
setRotation(testSpec.startRotation)
}
- transitions {
- setRotation(testSpec.endRotation)
- }
+ transitions { setRotation(testSpec.endRotation) }
}
- /**
- * Checks the position of the navigation bar at the start and end of the transition
- */
+ /** Checks the position of the navigation bar at the start and end of the transition */
@FlakyTest(bugId = 240499181)
@Test
override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
- /**
- * Checks that [testApp] layer is within [screenBoundsStart] at the start of the transition
- */
+ /** Checks that [testApp] layer is within [screenBoundsStart] at the start of the transition */
@Presubmit
@Test
fun fixedAppLayer_StartingBounds() {
- testSpec.assertLayersStart {
- visibleRegion(testApp).coversAtMost(screenBoundsStart)
- }
+ testSpec.assertLayersStart { visibleRegion(testApp).coversAtMost(screenBoundsStart) }
}
- /**
- * Checks that [testApp] layer is within [screenBoundsEnd] at the end of the transition
- */
+ /** Checks that [testApp] layer is within [screenBoundsEnd] at the end of the transition */
@Presubmit
@Test
fun fixedAppLayer_EndingBounds() {
- testSpec.assertLayersEnd {
- visibleRegion(testApp).coversAtMost(screenBoundsEnd)
- }
+ testSpec.assertLayersEnd { visibleRegion(testApp).coversAtMost(screenBoundsEnd) }
}
/**
- * Checks that [testApp] plus [pipApp] layers are within [screenBoundsEnd] at the start
- * of the transition
+ * Checks that [testApp] plus [pipApp] layers are within [screenBoundsEnd] at the start of the
+ * transition
*/
@Presubmit
@Test
@@ -122,8 +113,8 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS
}
/**
- * Checks that [testApp] plus [pipApp] layers are within [screenBoundsEnd] at the end
- * of the transition
+ * Checks that [testApp] plus [pipApp] layers are within [screenBoundsEnd] at the end of the
+ * transition
*/
@Presubmit
@Test
@@ -133,60 +124,44 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS
}
}
- /**
- * Checks that [pipApp] layer is within [screenBoundsStart] at the start of the transition
- */
+ /** Checks that [pipApp] layer is within [screenBoundsStart] at the start of the transition */
private fun pipLayerRotates_StartingBounds_internal() {
- testSpec.assertLayersStart {
- visibleRegion(pipApp).coversAtMost(screenBoundsStart)
- }
+ testSpec.assertLayersStart { visibleRegion(pipApp).coversAtMost(screenBoundsStart) }
}
- /**
- * Checks that [pipApp] layer is within [screenBoundsStart] at the start of the transition
- */
+ /** Checks that [pipApp] layer is within [screenBoundsStart] at the start of the transition */
@Presubmit
@Test
fun pipLayerRotates_StartingBounds() {
pipLayerRotates_StartingBounds_internal()
}
- /**
- * Checks that [pipApp] layer is within [screenBoundsEnd] at the end of the transition
- */
+ /** Checks that [pipApp] layer is within [screenBoundsEnd] at the end of the transition */
@Presubmit
@Test
fun pipLayerRotates_EndingBounds() {
- testSpec.assertLayersEnd {
- visibleRegion(pipApp).coversAtMost(screenBoundsEnd)
- }
+ testSpec.assertLayersEnd { visibleRegion(pipApp).coversAtMost(screenBoundsEnd) }
}
/**
- * Ensure that the [pipApp] window does not obscure the [testApp] at the start of the
- * transition
+ * Ensure that the [pipApp] window does not obscure the [testApp] at the start of the transition
*/
@Presubmit
@Test
fun pipIsAboveFixedAppWindow_Start() {
- testSpec.assertWmStart {
- isAboveWindow(pipApp, testApp)
- }
+ testSpec.assertWmStart { isAboveWindow(pipApp, testApp) }
}
/**
- * Ensure that the [pipApp] window does not obscure the [testApp] at the end of the
- * transition
+ * Ensure that the [pipApp] window does not obscure the [testApp] at the end of the transition
*/
@Presubmit
@Test
fun pipIsAboveFixedAppWindow_End() {
- testSpec.assertWmEnd {
- isAboveWindow(pipApp, testApp)
- }
+ testSpec.assertWmEnd { isAboveWindow(pipApp, testApp) }
}
- @FlakyTest(bugId = 240499181)
+ @Presubmit
@Test
override fun navBarLayerIsVisibleAtStartAndEnd() {
super.navBarLayerIsVisibleAtStartAndEnd()
@@ -196,15 +171,16 @@ open class PipRotationTest(testSpec: FlickerTestParameter) : PipTransition(testS
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance().getConfigRotationTests(
- supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90)
- )
+ return FlickerTestParameterFactory.getInstance()
+ .getConfigRotationTests(
+ supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90)
+ )
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt
index d868e98d0cf8..983cb1c6bafd 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipRotationTest_ShellTransit.kt
@@ -35,18 +35,21 @@ import org.junit.runners.Parameterized
* To run this test: `atest WMShellFlickerTests:PipRotationTest_ShellTransit`
*
* Actions:
+ * ```
* Launch a [pipApp] in pip mode
* Launch another app [fixedApp] (appears below pip)
* Rotate the screen from [testSpec.startRotation] to [testSpec.endRotation]
* (usually, 0->90 and 90->0)
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited from [PipTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -59,9 +62,8 @@ class PipRotationTest_ShellTransit(testSpec: FlickerTestParameter) : PipRotation
Assume.assumeTrue(isShellTransitionsEnabled)
}
- /** {@inheritDoc} */
+ /** {@inheritDoc} */
@FlakyTest
@Test
- override fun navBarLayerPositionAtStartAndEnd() =
- super.navBarLayerPositionAtStartAndEnd()
+ override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
index ff505a04290b..dfa25104ccc8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipTransition.kt
@@ -40,24 +40,21 @@ abstract class PipTransition(testSpec: FlickerTestParameter) : BaseTest(testSpec
}
fun doAction(broadcastAction: String) {
- instrumentation.context
- .sendBroadcast(createIntentWithAction(broadcastAction))
+ instrumentation.context.sendBroadcast(createIntentWithAction(broadcastAction))
}
companion object {
// Corresponds to ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
- @JvmStatic
- val ORIENTATION_LANDSCAPE = 0
+ @JvmStatic val ORIENTATION_LANDSCAPE = 0
// Corresponds to ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
- @JvmStatic
- val ORIENTATION_PORTRAIT = 1
+ @JvmStatic val ORIENTATION_PORTRAIT = 1
}
}
/**
- * Gets a configuration that handles basic setup and teardown of pip tests and that
- * launches the Pip app for test
+ * Gets a configuration that handles basic setup and teardown of pip tests and that launches the
+ * Pip app for test
*
* @param eachRun If the pip app should be launched in each run (otherwise only 1x per test)
* @param stringExtras Arguments to pass to the PIP launch intent
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt
index cdd768abd5bd..36909dd74245 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipAppHelperTv.kt
@@ -24,9 +24,7 @@ import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.helpers.PipAppHelper
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
-/**
- * Helper class for PIP app on AndroidTV
- */
+/** Helper class for PIP app on AndroidTV */
open class PipAppHelperTv(instrumentation: Instrumentation) : PipAppHelper(instrumentation) {
private val appSelector = By.pkg(`package`).depth(0)
@@ -61,17 +59,12 @@ open class PipAppHelperTv(instrumentation: Instrumentation) : PipAppHelper(instr
uiDevice.closeTvPipWindow()
}
- /**
- * Taps the pip window and dismisses it by clicking on the X button.
- */
+ /** Taps the pip window and dismisses it by clicking on the X button. */
override fun closePipWindow(wmHelper: WindowManagerStateHelper) {
uiDevice.closeTvPipWindow()
// Wait for animation to complete.
- wmHelper.StateSyncBuilder()
- .withPipGone()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withPipGone().withHomeActivityVisible().waitForAndVerify()
}
fun waitUntilClosed(): Boolean {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipTestBase.kt
index a16f5f6f1620..2cb18f948f0e 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/PipTestBase.kt
@@ -24,10 +24,7 @@ import androidx.test.uiautomator.UiDevice
import org.junit.Before
import org.junit.runners.Parameterized
-abstract class PipTestBase(
- protected val rotationName: String,
- protected val rotation: Int
-) {
+abstract class PipTestBase(protected val rotationName: String, protected val rotation: Int) {
val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation()
val uiDevice = UiDevice.getInstance(instrumentation)
val packageManager: PackageManager = instrumentation.context.packageManager
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt
index 31fb16ffbd3e..8a073abf032c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipBasicTest.kt
@@ -25,16 +25,11 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
-/**
- * Test Pip Menu on TV.
- * To run this test: `atest WMShellFlickerTests:TvPipBasicTest`
- */
+/** Test Pip Menu on TV. To run this test: `atest WMShellFlickerTests:TvPipBasicTest` */
@RequiresDevice
@RunWith(Parameterized::class)
-class TvPipBasicTest(
- private val radioButtonId: String,
- private val pipWindowRatio: Rational?
-) : TvPipTestBase() {
+class TvPipBasicTest(private val radioButtonId: String, private val pipWindowRatio: Rational?) :
+ TvPipTestBase() {
@Test
fun enterPip_openMenu_pressBack_closePip() {
@@ -45,8 +40,8 @@ class TvPipBasicTest(
testApp.clickObject(radioButtonId)
testApp.clickEnterPipButton(wmHelper)
- val actualRatio: Float = testApp.ui?.visibleBounds?.ratio
- ?: fail("Application UI not found")
+ val actualRatio: Float =
+ testApp.ui?.visibleBounds?.ratio ?: fail("Application UI not found")
pipWindowRatio?.let { expectedRatio ->
assertEquals("Wrong Pip window ratio", expectedRatio.toFloat(), actualRatio)
}
@@ -62,7 +57,8 @@ class TvPipBasicTest(
// Make sure Pip Window ration remained the same after Pip menu was closed
testApp.ui?.visibleBounds?.let { newBounds ->
assertEquals("Pip window ratio has changed", actualRatio, newBounds.ratio)
- } ?: fail("Application UI not found")
+ }
+ ?: fail("Application UI not found")
// Close Pip
testApp.closePipWindow()
@@ -77,10 +73,10 @@ class TvPipBasicTest(
fun getParams(): Collection<Array<Any?>> {
infix fun Int.to(denominator: Int) = Rational(this, denominator)
return listOf(
- arrayOf("ratio_default", null),
- arrayOf("ratio_square", 1 to 1),
- arrayOf("ratio_wide", 2 to 1),
- arrayOf("ratio_tall", 1 to 2)
+ arrayOf("ratio_default", null),
+ arrayOf("ratio_square", 1 to 1),
+ arrayOf("ratio_wide", 2 to 1),
+ arrayOf("ratio_tall", 1 to 2)
)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
index 68dbbfb89b6c..7403aab7d4c0 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
@@ -27,28 +27,26 @@ import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
-/**
- * Test Pip Menu on TV.
- * To run this test: `atest WMShellFlickerTests:TvPipMenuTests`
- */
+/** Test Pip Menu on TV. To run this test: `atest WMShellFlickerTests:TvPipMenuTests` */
@RequiresDevice
class TvPipMenuTests : TvPipTestBase() {
private val systemUiResources =
- packageManager.getResourcesForApplication(SYSTEM_UI_PACKAGE_NAME)
- private val pipBoundsWhileInMenu: Rect = systemUiResources.run {
- val bounds = getString(getIdentifier("pip_menu_bounds", "string",
- SYSTEM_UI_PACKAGE_NAME))
- Rect.unflattenFromString(bounds) ?: error("Could not retrieve PiP menu bounds")
- }
- private val playButtonDescription = systemUiResources.run {
- getString(getIdentifier("pip_play", "string",
- SYSTEM_UI_PACKAGE_NAME))
- }
- private val pauseButtonDescription = systemUiResources.run {
- getString(getIdentifier("pip_pause", "string",
- SYSTEM_UI_PACKAGE_NAME))
- }
+ packageManager.getResourcesForApplication(SYSTEM_UI_PACKAGE_NAME)
+ private val pipBoundsWhileInMenu: Rect =
+ systemUiResources.run {
+ val bounds =
+ getString(getIdentifier("pip_menu_bounds", "string", SYSTEM_UI_PACKAGE_NAME))
+ Rect.unflattenFromString(bounds) ?: error("Could not retrieve PiP menu bounds")
+ }
+ private val playButtonDescription =
+ systemUiResources.run {
+ getString(getIdentifier("pip_play", "string", SYSTEM_UI_PACKAGE_NAME))
+ }
+ private val pauseButtonDescription =
+ systemUiResources.run {
+ getString(getIdentifier("pip_pause", "string", SYSTEM_UI_PACKAGE_NAME))
+ }
@Before
fun tvPipMenuTestsTestUp() {
@@ -61,20 +59,29 @@ class TvPipMenuTests : TvPipTestBase() {
enterPip_openMenu_assertShown()
// Make sure the PiP task is positioned where it should be.
- val activityBounds: Rect = testApp.ui?.visibleBounds
- ?: error("Could not retrieve Pip Activity bounds")
- assertTrue("Pip Activity is positioned correctly while Pip menu is shown",
- pipBoundsWhileInMenu == activityBounds)
+ val activityBounds: Rect =
+ testApp.ui?.visibleBounds ?: error("Could not retrieve Pip Activity bounds")
+ assertTrue(
+ "Pip Activity is positioned correctly while Pip menu is shown",
+ pipBoundsWhileInMenu == activityBounds
+ )
// Make sure the Pip Menu Actions are positioned correctly.
uiDevice.findTvPipMenuControls()?.visibleBounds?.run {
- assertTrue("Pip Menu Actions should be positioned below the Activity in Pip",
- top >= activityBounds.bottom)
- assertTrue("Pip Menu Actions should be positioned central horizontally",
- centerX() == uiDevice.displayWidth / 2)
- assertTrue("Pip Menu Actions should be fully shown on the screen",
- left >= 0 && right <= uiDevice.displayWidth && bottom <= uiDevice.displayHeight)
- } ?: error("Could not retrieve Pip Menu Actions bounds")
+ assertTrue(
+ "Pip Menu Actions should be positioned below the Activity in Pip",
+ top >= activityBounds.bottom
+ )
+ assertTrue(
+ "Pip Menu Actions should be positioned central horizontally",
+ centerX() == uiDevice.displayWidth / 2
+ )
+ assertTrue(
+ "Pip Menu Actions should be fully shown on the screen",
+ left >= 0 && right <= uiDevice.displayWidth && bottom <= uiDevice.displayHeight
+ )
+ }
+ ?: error("Could not retrieve Pip Menu Actions bounds")
testApp.closePipWindow()
}
@@ -107,7 +114,7 @@ class TvPipMenuTests : TvPipTestBase() {
// PiP menu should contain the Close button
uiDevice.findTvPipMenuCloseButton()
- ?: fail("\"Close PIP\" button should be shown in Pip menu")
+ ?: fail("\"Close PIP\" button should be shown in Pip menu")
// Clicking on the Close button should close the app
uiDevice.clickTvPipMenuCloseButton()
@@ -120,13 +127,15 @@ class TvPipMenuTests : TvPipTestBase() {
// PiP menu should contain the Fullscreen button
uiDevice.findTvPipMenuFullscreenButton()
- ?: fail("\"Full screen\" button should be shown in Pip menu")
+ ?: fail("\"Full screen\" button should be shown in Pip menu")
// Clicking on the fullscreen button should return app to the fullscreen mode.
// Click, wait for the app to go fullscreen
uiDevice.clickTvPipMenuFullscreenButton()
- assertTrue("\"Full screen\" button should open the app fullscreen",
- wait { testApp.ui?.isFullscreen(uiDevice) ?: false })
+ assertTrue(
+ "\"Full screen\" button should open the app fullscreen",
+ wait { testApp.ui?.isFullscreen(uiDevice) ?: false }
+ )
// Close the app
uiDevice.pressBack()
@@ -143,8 +152,10 @@ class TvPipMenuTests : TvPipTestBase() {
// PiP menu should contain the Pause button
uiDevice.findTvPipMenuElementWithDescription(pauseButtonDescription)
- ?: fail("\"Pause\" button should be shown in Pip menu if there is an active " +
- "playing media session.")
+ ?: fail(
+ "\"Pause\" button should be shown in Pip menu if there is an active " +
+ "playing media session."
+ )
// When we pause media, the button should change from Pause to Play
uiDevice.clickTvPipMenuElementWithDescription(pauseButtonDescription)
@@ -152,8 +163,10 @@ class TvPipMenuTests : TvPipTestBase() {
assertFullscreenAndCloseButtonsAreShown()
// PiP menu should contain the Play button now
uiDevice.waitForTvPipMenuElementWithDescription(playButtonDescription)
- ?: fail("\"Play\" button should be shown in Pip menu if there is an active " +
- "paused media session.")
+ ?: fail(
+ "\"Play\" button should be shown in Pip menu if there is an active " +
+ "paused media session."
+ )
testApp.closePipWindow()
}
@@ -166,11 +179,11 @@ class TvPipMenuTests : TvPipTestBase() {
// PiP menu should contain "No-Op", "Off" and "Clear" buttons...
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_NO_OP)
- ?: fail("\"No-Op\" button should be shown in Pip menu")
+ ?: fail("\"No-Op\" button should be shown in Pip menu")
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_OFF)
- ?: fail("\"Off\" button should be shown in Pip menu")
+ ?: fail("\"Off\" button should be shown in Pip menu")
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_CLEAR)
- ?: fail("\"Clear\" button should be shown in Pip menu")
+ ?: fail("\"Clear\" button should be shown in Pip menu")
// ... and should also contain the "Full screen" and "Close" buttons.
assertFullscreenAndCloseButtonsAreShown()
@@ -178,31 +191,34 @@ class TvPipMenuTests : TvPipTestBase() {
// Invoking the "Off" action should replace it with the "On" action/button and should
// remove the "No-Op" action/button. "Clear" action/button should remain in the menu ...
uiDevice.waitForTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_ON)
- ?: fail("\"On\" button should be shown in Pip for a corresponding custom action")
- assertNull("\"No-Op\" button should not be shown in Pip menu",
- uiDevice.findTvPipMenuElementWithDescription(
- ActivityOptions.Pip.MENU_ACTION_NO_OP))
+ ?: fail("\"On\" button should be shown in Pip for a corresponding custom action")
+ assertNull(
+ "\"No-Op\" button should not be shown in Pip menu",
+ uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_NO_OP)
+ )
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_CLEAR)
- ?: fail("\"Clear\" button should be shown in Pip menu")
+ ?: fail("\"Clear\" button should be shown in Pip menu")
// ... as well as the "Full screen" and "Close" buttons.
assertFullscreenAndCloseButtonsAreShown()
uiDevice.clickTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_CLEAR)
// Invoking the "Clear" action should remove all the custom actions and their corresponding
// buttons, ...
- uiDevice.waitUntilTvPipMenuElementWithDescriptionIsGone(
- ActivityOptions.Pip.MENU_ACTION_ON)?.also {
- isGone -> if (!isGone) fail("\"On\" button should not be shown in Pip menu")
- }
- assertNull("\"Off\" button should not be shown in Pip menu",
- uiDevice.findTvPipMenuElementWithDescription(
- ActivityOptions.Pip.MENU_ACTION_OFF))
- assertNull("\"Clear\" button should not be shown in Pip menu",
- uiDevice.findTvPipMenuElementWithDescription(
- ActivityOptions.Pip.MENU_ACTION_CLEAR))
- assertNull("\"No-Op\" button should not be shown in Pip menu",
- uiDevice.findTvPipMenuElementWithDescription(
- ActivityOptions.Pip.MENU_ACTION_NO_OP))
+ uiDevice
+ .waitUntilTvPipMenuElementWithDescriptionIsGone(ActivityOptions.Pip.MENU_ACTION_ON)
+ ?.also { isGone -> if (!isGone) fail("\"On\" button should not be shown in Pip menu") }
+ assertNull(
+ "\"Off\" button should not be shown in Pip menu",
+ uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_OFF)
+ )
+ assertNull(
+ "\"Clear\" button should not be shown in Pip menu",
+ uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_CLEAR)
+ )
+ assertNull(
+ "\"No-Op\" button should not be shown in Pip menu",
+ uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_NO_OP)
+ )
// ... but the menu should still contain the "Full screen" and "Close" buttons.
assertFullscreenAndCloseButtonsAreShown()
@@ -218,25 +234,31 @@ class TvPipMenuTests : TvPipTestBase() {
// PiP menu should contain "No-Op", "Off" and "Clear" buttons for the custom actions...
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_NO_OP)
- ?: fail("\"No-Op\" button should be shown in Pip menu")
+ ?: fail("\"No-Op\" button should be shown in Pip menu")
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_OFF)
- ?: fail("\"Off\" button should be shown in Pip menu")
+ ?: fail("\"Off\" button should be shown in Pip menu")
uiDevice.findTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_CLEAR)
- ?: fail("\"Clear\" button should be shown in Pip menu")
+ ?: fail("\"Clear\" button should be shown in Pip menu")
// ... should also contain the "Full screen" and "Close" buttons, ...
assertFullscreenAndCloseButtonsAreShown()
// ... but should not contain media buttons.
- assertNull("\"Play\" button should not be shown in menu when there are custom actions",
- uiDevice.findTvPipMenuElementWithDescription(playButtonDescription))
- assertNull("\"Pause\" button should not be shown in menu when there are custom actions",
- uiDevice.findTvPipMenuElementWithDescription(pauseButtonDescription))
+ assertNull(
+ "\"Play\" button should not be shown in menu when there are custom actions",
+ uiDevice.findTvPipMenuElementWithDescription(playButtonDescription)
+ )
+ assertNull(
+ "\"Pause\" button should not be shown in menu when there are custom actions",
+ uiDevice.findTvPipMenuElementWithDescription(pauseButtonDescription)
+ )
uiDevice.clickTvPipMenuElementWithDescription(ActivityOptions.Pip.MENU_ACTION_CLEAR)
// Invoking the "Clear" action should remove all the custom actions, which should bring up
// media buttons...
uiDevice.waitForTvPipMenuElementWithDescription(pauseButtonDescription)
- ?: fail("\"Pause\" button should be shown in Pip menu if there is an active " +
- "playing media session.")
+ ?: fail(
+ "\"Pause\" button should be shown in Pip menu if there is an active " +
+ "playing media session."
+ )
// ... while the "Full screen" and "Close" buttons should remain in the menu.
assertFullscreenAndCloseButtonsAreShown()
@@ -252,8 +274,8 @@ class TvPipMenuTests : TvPipTestBase() {
private fun assertFullscreenAndCloseButtonsAreShown() {
uiDevice.findTvPipMenuCloseButton()
- ?: fail("\"Close PIP\" button should be shown in Pip menu")
+ ?: fail("\"Close PIP\" button should be shown in Pip menu")
uiDevice.findTvPipMenuFullscreenButton()
- ?: fail("\"Full screen\" button should be shown in Pip menu")
+ ?: fail("\"Full screen\" button should be shown in Pip menu")
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt
index 134e97bd46e7..90406c510bad 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt
@@ -34,8 +34,8 @@ import org.junit.Before
import org.junit.Test
/**
- * Test Pip Notifications on TV.
- * To run this test: `atest WMShellFlickerTests:TvPipNotificationTests`
+ * Test Pip Notifications on TV. To run this test: `atest
+ * WMShellFlickerTests:TvPipNotificationTests`
*/
@RequiresDevice
class TvPipNotificationTests : TvPipTestBase() {
@@ -58,13 +58,17 @@ class TvPipNotificationTests : TvPipTestBase() {
testApp.launchViaIntent()
testApp.clickEnterPipButton(wmHelper)
- assertNotNull("Pip notification should have been posted",
- waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.appName) })
+ assertNotNull(
+ "Pip notification should have been posted",
+ waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.appName) }
+ )
testApp.closePipWindow()
- assertTrue("Pip notification should have been dismissed",
- waitForNotificationToDisappear { it.isPipNotificationWithTitle(testApp.appName) })
+ assertTrue(
+ "Pip notification should have been dismissed",
+ waitForNotificationToDisappear { it.isPipNotificationWithTitle(testApp.appName) }
+ )
}
@Test
@@ -72,17 +76,20 @@ class TvPipNotificationTests : TvPipTestBase() {
testApp.launchViaIntent()
testApp.clickEnterPipButton(wmHelper)
- val notification: StatusBarNotification = waitForNotificationToAppear {
- it.isPipNotificationWithTitle(testApp.appName)
- } ?: fail("Pip notification should have been posted")
+ val notification: StatusBarNotification =
+ waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.appName) }
+ ?: fail("Pip notification should have been posted")
- notification.deleteIntent?.send()
- ?: fail("Pip notification should contain `delete_intent`")
+ notification.deleteIntent?.send() ?: fail("Pip notification should contain `delete_intent`")
- assertTrue("Pip should have closed by sending the `delete_intent`",
- testApp.waitUntilClosed())
- assertTrue("Pip notification should have been dismissed",
- waitForNotificationToDisappear { it.isPipNotificationWithTitle(testApp.appName) })
+ assertTrue(
+ "Pip should have closed by sending the `delete_intent`",
+ testApp.waitUntilClosed()
+ )
+ assertTrue(
+ "Pip notification should have been dismissed",
+ waitForNotificationToDisappear { it.isPipNotificationWithTitle(testApp.appName) }
+ )
}
@Test
@@ -90,15 +97,17 @@ class TvPipNotificationTests : TvPipTestBase() {
testApp.launchViaIntent(wmHelper)
testApp.clickEnterPipButton(wmHelper)
- val notification: StatusBarNotification = waitForNotificationToAppear {
- it.isPipNotificationWithTitle(testApp.appName)
- } ?: fail("Pip notification should have been posted")
+ val notification: StatusBarNotification =
+ waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.appName) }
+ ?: fail("Pip notification should have been posted")
notification.contentIntent?.send()
?: fail("Pip notification should contain `content_intent`")
- assertNotNull("Pip menu should have been shown after sending `content_intent`",
- uiDevice.waitForTvPipMenu())
+ assertNotNull(
+ "Pip menu should have been shown after sending `content_intent`",
+ uiDevice.waitForTvPipMenu()
+ )
uiDevice.pressBack()
testApp.closePipWindow()
@@ -112,35 +121,38 @@ class TvPipNotificationTests : TvPipTestBase() {
testApp.clickEnterPipButton(wmHelper)
// Wait for the correct notification to show up...
- waitForNotificationToAppear {
- it.isPipNotificationWithTitle(TITLE_MEDIA_SESSION_PLAYING)
- } ?: fail("Pip notification with media session title should have been posted")
+ waitForNotificationToAppear { it.isPipNotificationWithTitle(TITLE_MEDIA_SESSION_PLAYING) }
+ ?: fail("Pip notification with media session title should have been posted")
// ... and make sure "regular" PiP notification is now shown
- assertNull("Regular notification should not have been posted",
- findNotification { it.isPipNotificationWithTitle(testApp.appName) })
+ assertNull(
+ "Regular notification should not have been posted",
+ findNotification { it.isPipNotificationWithTitle(testApp.appName) }
+ )
// Pause the media session. When paused the application updates the title for the media
// session. This change should be reflected in the notification.
testApp.pauseMedia()
// Wait for the "paused" notification to show up...
- waitForNotificationToAppear {
- it.isPipNotificationWithTitle(TITLE_MEDIA_SESSION_PAUSED)
- } ?: fail("Pip notification with media session title should have been posted")
+ waitForNotificationToAppear { it.isPipNotificationWithTitle(TITLE_MEDIA_SESSION_PAUSED) }
+ ?: fail("Pip notification with media session title should have been posted")
// ... and make sure "playing" PiP notification is gone
- assertNull("Regular notification should not have been posted",
- findNotification { it.isPipNotificationWithTitle(TITLE_MEDIA_SESSION_PLAYING) })
+ assertNull(
+ "Regular notification should not have been posted",
+ findNotification { it.isPipNotificationWithTitle(TITLE_MEDIA_SESSION_PLAYING) }
+ )
// Now stop the media session, which should revert the title to the "default" one.
testApp.stopMedia()
// Wait for the "regular" notification to show up...
- waitForNotificationToAppear {
- it.isPipNotificationWithTitle(testApp.appName)
- } ?: fail("Pip notification with media session title should have been posted")
+ waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.appName) }
+ ?: fail("Pip notification with media session title should have been posted")
// ... and make sure previous ("paused") notification is gone
- assertNull("Regular notification should not have been posted",
- findNotification { it.isPipNotificationWithTitle(TITLE_MEDIA_SESSION_PAUSED) })
+ assertNull(
+ "Regular notification should not have been posted",
+ findNotification { it.isPipNotificationWithTitle(TITLE_MEDIA_SESSION_PAUSED) }
+ )
testApp.closePipWindow()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
index aeff0ac9f4f2..dc1fe4761757 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
@@ -68,7 +68,8 @@ abstract class TvPipTestBase : PipTestBase(rotationToString(ROTATION_0), ROTATIO
fun start() {
hasDied = false
uiAutomation.adoptShellPermissionIdentity(
- android.Manifest.permission.SET_ACTIVITY_WATCHER)
+ android.Manifest.permission.SET_ACTIVITY_WATCHER
+ )
activityManager.registerProcessObserver(this)
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
index 1c663409b913..b0adbe1d07ce 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
@@ -33,32 +33,31 @@ private const val TV_PIP_MENU_FULLSCREEN_BUTTON_ID = "tv_pip_menu_fullscreen_but
private const val FOCUS_ATTEMPTS = 10
private const val WAIT_TIME_MS = 3_000L
-private val TV_PIP_MENU_SELECTOR =
- By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_ROOT_ID)
+private val TV_PIP_MENU_SELECTOR = By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_ROOT_ID)
private val TV_PIP_MENU_BUTTONS_CONTAINER_SELECTOR =
- By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_BUTTONS_CONTAINER_ID)
+ By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_BUTTONS_CONTAINER_ID)
private val TV_PIP_MENU_CLOSE_BUTTON_SELECTOR =
- By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_CLOSE_BUTTON_ID)
+ By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_CLOSE_BUTTON_ID)
private val TV_PIP_MENU_FULLSCREEN_BUTTON_SELECTOR =
- By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_FULLSCREEN_BUTTON_ID)
+ By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_FULLSCREEN_BUTTON_ID)
fun UiDevice.waitForTvPipMenu(): UiObject2? =
- wait(Until.findObject(TV_PIP_MENU_SELECTOR), WAIT_TIME_MS)
+ wait(Until.findObject(TV_PIP_MENU_SELECTOR), WAIT_TIME_MS)
fun UiDevice.waitForTvPipMenuToClose(): Boolean =
- wait(Until.gone(TV_PIP_MENU_SELECTOR), WAIT_TIME_MS)
+ wait(Until.gone(TV_PIP_MENU_SELECTOR), WAIT_TIME_MS)
fun UiDevice.findTvPipMenuControls(): UiObject2? =
- findTvPipMenuElement(TV_PIP_MENU_BUTTONS_CONTAINER_SELECTOR)
+ findTvPipMenuElement(TV_PIP_MENU_BUTTONS_CONTAINER_SELECTOR)
fun UiDevice.findTvPipMenuCloseButton(): UiObject2? =
- findTvPipMenuElement(TV_PIP_MENU_CLOSE_BUTTON_SELECTOR)
+ findTvPipMenuElement(TV_PIP_MENU_CLOSE_BUTTON_SELECTOR)
fun UiDevice.findTvPipMenuFullscreenButton(): UiObject2? =
- findTvPipMenuElement(TV_PIP_MENU_FULLSCREEN_BUTTON_SELECTOR)
+ findTvPipMenuElement(TV_PIP_MENU_FULLSCREEN_BUTTON_SELECTOR)
fun UiDevice.findTvPipMenuElementWithDescription(desc: String): UiObject2? =
- findTvPipMenuElement(By.desc(desc))
+ findTvPipMenuElement(By.desc(desc))
private fun UiDevice.findTvPipMenuElement(selector: BySelector): UiObject2? =
findObject(TV_PIP_MENU_SELECTOR)?.findObject(selector)
@@ -70,11 +69,10 @@ fun UiDevice.waitForTvPipMenuElementWithDescription(desc: String): UiObject2? {
// descendant and then retrieve the element from the menu and return to the caller of this
// method.
val elementSelector = By.desc(desc)
- val menuContainingElementSelector = By.copy(TV_PIP_MENU_SELECTOR)
- .hasDescendant(elementSelector)
+ val menuContainingElementSelector = By.copy(TV_PIP_MENU_SELECTOR).hasDescendant(elementSelector)
return wait(Until.findObject(menuContainingElementSelector), WAIT_TIME_MS)
- ?.findObject(elementSelector)
+ ?.findObject(elementSelector)
}
fun UiDevice.waitUntilTvPipMenuElementWithDescriptionIsGone(desc: String): Boolean? {
@@ -86,18 +84,17 @@ fun UiDevice.waitUntilTvPipMenuElementWithDescriptionIsGone(desc: String): Boole
fun UiDevice.clickTvPipMenuCloseButton() {
focusOnAndClickTvPipMenuElement(TV_PIP_MENU_CLOSE_BUTTON_SELECTOR) ||
- error("Could not focus on the Close button")
+ error("Could not focus on the Close button")
}
fun UiDevice.clickTvPipMenuFullscreenButton() {
focusOnAndClickTvPipMenuElement(TV_PIP_MENU_FULLSCREEN_BUTTON_SELECTOR) ||
- error("Could not focus on the Fullscreen button")
+ error("Could not focus on the Fullscreen button")
}
fun UiDevice.clickTvPipMenuElementWithDescription(desc: String) {
- focusOnAndClickTvPipMenuElement(By.desc(desc)
- .pkg(SYSTEM_UI_PACKAGE_NAME)) ||
- error("Could not focus on the Pip menu object with \"$desc\" description")
+ focusOnAndClickTvPipMenuElement(By.desc(desc).pkg(SYSTEM_UI_PACKAGE_NAME)) ||
+ error("Could not focus on the Pip menu object with \"$desc\" description")
// So apparently Accessibility framework on TV is not very reliable and sometimes the state of
// the tree of accessibility nodes as seen by the accessibility clients kind of lags behind of
// the "real" state of the "UI tree". It seems, however, that moving focus around the tree
@@ -110,7 +107,8 @@ fun UiDevice.clickTvPipMenuElementWithDescription(desc: String) {
private fun UiDevice.focusOnAndClickTvPipMenuElement(selector: BySelector): Boolean {
repeat(FOCUS_ATTEMPTS) {
- val element = findTvPipMenuElement(selector)
+ val element =
+ findTvPipMenuElement(selector)
?: error("The Pip Menu element we try to focus on is gone.")
if (element.isFocusedOrHasFocusedChild) {
@@ -119,10 +117,11 @@ private fun UiDevice.focusOnAndClickTvPipMenuElement(selector: BySelector): Bool
}
findTvPipMenuElement(By.focused(true))?.let { focused ->
- if (element.visibleCenter.x < focused.visibleCenter.x)
- pressDPadLeft() else pressDPadRight()
+ if (element.visibleCenter.x < focused.visibleCenter.x) pressDPadLeft()
+ else pressDPadRight()
waitForIdle()
- } ?: error("Pip menu does not contain a focused element")
+ }
+ ?: error("Pip menu does not contain a focused element")
}
return false
@@ -155,9 +154,8 @@ private fun UiDevice.moveFocus() {
fun UiDevice.pressWindowKey() = pressKeyCode(KeyEvent.KEYCODE_WINDOW)
-fun UiObject2.isFullscreen(uiDevice: UiDevice): Boolean = visibleBounds.run {
- height() == uiDevice.displayHeight && width() == uiDevice.displayWidth
-}
+fun UiObject2.isFullscreen(uiDevice: UiDevice): Boolean =
+ visibleBounds.run { height() == uiDevice.displayHeight && width() == uiDevice.displayWidth }
val UiObject2.isFocusedOrHasFocusedChild: Boolean
get() = isFocused || findObject(By.focused(true)) != null
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
index 5bed66339ee5..9b1247abfb71 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/CopyContentInSplit.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.IwTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.WindowManagerPolicyConstants
import androidx.test.filters.RequiresDevice
@@ -54,12 +53,14 @@ class CopyContentInSplit(testSpec: FlickerTestParameter) : SplitScreenBase(testS
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
- setup {
- SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, textEditApp)
- }
+ setup { SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, textEditApp) }
transitions {
SplitScreenUtils.copyContentInSplit(
- instrumentation, device, primaryApp, textEditApp)
+ instrumentation,
+ device,
+ primaryApp,
+ textEditApp
+ )
}
}
@@ -82,94 +83,87 @@ class CopyContentInSplit(testSpec: FlickerTestParameter) : SplitScreenBase(testS
@Test
fun splitScreenDividerKeepVisible() = testSpec.layerKeepVisible(SPLIT_SCREEN_DIVIDER_COMPONENT)
- @Presubmit
- @Test
- fun primaryAppLayerKeepVisible() = testSpec.layerKeepVisible(primaryApp)
+ @Presubmit @Test fun primaryAppLayerKeepVisible() = testSpec.layerKeepVisible(primaryApp)
- @Presubmit
- @Test
- fun textEditAppLayerKeepVisible() = testSpec.layerKeepVisible(textEditApp)
+ @Presubmit @Test fun textEditAppLayerKeepVisible() = testSpec.layerKeepVisible(textEditApp)
@Presubmit
@Test
- fun primaryAppBoundsKeepVisible() = testSpec.splitAppLayerBoundsKeepVisible(
- primaryApp, landscapePosLeft = tapl.isTablet, portraitPosTop = false)
+ fun primaryAppBoundsKeepVisible() =
+ testSpec.splitAppLayerBoundsKeepVisible(
+ primaryApp,
+ landscapePosLeft = tapl.isTablet,
+ portraitPosTop = false
+ )
@Presubmit
@Test
- fun textEditAppBoundsKeepVisible() = testSpec.splitAppLayerBoundsKeepVisible(
- textEditApp, landscapePosLeft = !tapl.isTablet, portraitPosTop = true)
+ fun textEditAppBoundsKeepVisible() =
+ testSpec.splitAppLayerBoundsKeepVisible(
+ textEditApp,
+ landscapePosLeft = !tapl.isTablet,
+ portraitPosTop = true
+ )
- @Presubmit
- @Test
- fun primaryAppWindowKeepVisible() = testSpec.appWindowKeepVisible(primaryApp)
+ @Presubmit @Test fun primaryAppWindowKeepVisible() = testSpec.appWindowKeepVisible(primaryApp)
- @Presubmit
- @Test
- fun textEditAppWindowKeepVisible() = testSpec.appWindowKeepVisible(textEditApp)
+ @Presubmit @Test fun textEditAppWindowKeepVisible() = testSpec.appWindowKeepVisible(textEditApp)
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun entireScreenCovered() =
super.entireScreenCovered()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarLayerIsVisibleAtStartAndEnd() =
- super.navBarLayerIsVisibleAtStartAndEnd()
+ override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarLayerPositionAtStartAndEnd() =
- super.navBarLayerPositionAtStartAndEnd()
+ override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarWindowIsAlwaysVisible() =
- super.navBarWindowIsAlwaysVisible()
+ override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun statusBarLayerIsVisibleAtStartAndEnd() =
super.statusBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun statusBarWindowIsAlwaysVisible() =
- super.statusBarWindowIsAlwaysVisible()
+ override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() =
- super.taskBarLayerIsVisibleAtStartAndEnd()
+ override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun taskBarWindowIsAlwaysVisible() =
- super.taskBarWindowIsAlwaysVisible()
+ override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
@@ -178,10 +172,12 @@ class CopyContentInSplit(testSpec: FlickerTestParameter) : SplitScreenBase(testS
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
- // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
- supportedNavigationModes =
- listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY))
+ return FlickerTestParameterFactory.getInstance()
+ .getConfigNonRotationTests(
+ // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
+ supportedNavigationModes =
+ listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY)
+ )
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
index 90e11f205ff1..cb49e18d672c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/DismissSplitScreenByGoHome.kt
@@ -18,7 +18,6 @@ package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.IwTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.WindowManagerPolicyConstants
import androidx.test.filters.RequiresDevice
@@ -107,67 +106,67 @@ class DismissSplitScreenByGoHome(
fun secondaryAppWindowBecomesInvisible() = testSpec.appWindowBecomesInvisible(secondaryApp)
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun entireScreenCovered() =
super.entireScreenCovered()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun navBarLayerIsVisibleAtStartAndEnd() =
super.navBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun navBarLayerPositionAtStartAndEnd() =
super.navBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun navBarWindowIsAlwaysVisible() =
super.navBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun statusBarLayerIsVisibleAtStartAndEnd() =
super.statusBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun statusBarLayerPositionAtStartAndEnd() =
super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun statusBarWindowIsAlwaysVisible() =
super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun taskBarLayerIsVisibleAtStartAndEnd() =
super.taskBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun taskBarWindowIsAlwaysVisible() =
super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
index 6d821c491e82..504238f15b8c 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/EnterSplitScreenFromOverview.kt
@@ -117,13 +117,13 @@ class EnterSplitScreenFromOverview(testSpec: FlickerTestParameter) : SplitScreen
fun secondaryAppWindowBecomesVisible() = testSpec.appWindowBecomesVisible(secondaryApp)
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun entireScreenCovered() =
super.entireScreenCovered()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun navBarLayerIsVisibleAtStartAndEnd() =
super.navBarLayerIsVisibleAtStartAndEnd()
@@ -135,49 +135,49 @@ class EnterSplitScreenFromOverview(testSpec: FlickerTestParameter) : SplitScreen
super.navBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun navBarWindowIsAlwaysVisible() =
super.navBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun statusBarLayerIsVisibleAtStartAndEnd() =
super.statusBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun statusBarLayerPositionAtStartAndEnd() =
super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun statusBarWindowIsAlwaysVisible() =
super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun taskBarLayerIsVisibleAtStartAndEnd() =
super.taskBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun taskBarWindowIsAlwaysVisible() =
super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
index e57ac91617b7..6453ed869681 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SplitScreenUtils.kt
@@ -76,15 +76,15 @@ internal object SplitScreenUtils {
fun getSendNotification(instrumentation: Instrumentation): NotificationAppHelper =
NotificationAppHelper(instrumentation)
- fun getIme(instrumentation: Instrumentation): ImeAppHelper =
- ImeAppHelper(instrumentation)
+ fun getIme(instrumentation: Instrumentation): ImeAppHelper = ImeAppHelper(instrumentation)
fun waitForSplitComplete(
wmHelper: WindowManagerStateHelper,
primaryApp: IComponentMatcher,
secondaryApp: IComponentMatcher,
) {
- wmHelper.StateSyncBuilder()
+ wmHelper
+ .StateSyncBuilder()
.withWindowSurfaceAppeared(primaryApp)
.withWindowSurfaceAppeared(secondaryApp)
.withSplitDividerVisible()
@@ -101,9 +101,7 @@ internal object SplitScreenUtils {
primaryApp.launchViaIntent(wmHelper)
secondaryApp.launchViaIntent(wmHelper)
tapl.goHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
splitFromOverview(tapl)
waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
@@ -113,12 +111,11 @@ internal object SplitScreenUtils {
// In landscape, tablet will let the first app split to right side, and phone will
// split to left side.
if (tapl.isTablet) {
- tapl.workspace.switchToOverview().overviewActions
- .clickSplit()
- .currentTask
- .open()
+ tapl.workspace.switchToOverview().overviewActions.clickSplit().currentTask.open()
} else {
- tapl.workspace.switchToOverview().currentTask
+ tapl.workspace
+ .switchToOverview()
+ .currentTask
.tapMenu()
.tapSplitMenuItem()
.currentTask
@@ -132,28 +129,33 @@ internal object SplitScreenUtils {
device: UiDevice,
wmHelper: WindowManagerStateHelper
) {
- val displayBounds = wmHelper.currentState.layerState
- .displays.firstOrNull { !it.isVirtual }
- ?.layerStackSpace
- ?: error("Display not found")
+ val displayBounds =
+ wmHelper.currentState.layerState.displays.firstOrNull { !it.isVirtual }?.layerStackSpace
+ ?: error("Display not found")
// Pull down the notifications
device.swipe(
- displayBounds.centerX(), 5,
- displayBounds.centerX(), displayBounds.bottom, 50 /* steps */
+ displayBounds.centerX(),
+ 5,
+ displayBounds.centerX(),
+ displayBounds.bottom,
+ 50 /* steps */
)
SystemClock.sleep(TIMEOUT_MS)
// Find the target notification
- val notificationScroller = device.wait(
- Until.findObject(notificationScrollerSelector), TIMEOUT_MS
- ) ?: error ("Unable to find view $notificationScrollerSelector")
+ val notificationScroller =
+ device.wait(Until.findObject(notificationScrollerSelector), TIMEOUT_MS)
+ ?: error("Unable to find view $notificationScrollerSelector")
var notificationContent = notificationScroller.findObject(notificationContentSelector)
while (notificationContent == null) {
device.swipe(
- displayBounds.centerX(), displayBounds.centerY(),
- displayBounds.centerX(), displayBounds.centerY() - 150, 20 /* steps */
+ displayBounds.centerX(),
+ displayBounds.centerY(),
+ displayBounds.centerX(),
+ displayBounds.centerY() - 150,
+ 20 /* steps */
)
notificationContent = notificationScroller.findObject(notificationContentSelector)
}
@@ -164,24 +166,33 @@ internal object SplitScreenUtils {
val dragEnd = Point(displayBounds.width / 4, displayBounds.width / 4)
val downTime = SystemClock.uptimeMillis()
- touch(
- instrumentation, MotionEvent.ACTION_DOWN, downTime, downTime,
- TIMEOUT_MS, dragStart
- )
+ touch(instrumentation, MotionEvent.ACTION_DOWN, downTime, downTime, TIMEOUT_MS, dragStart)
// It needs a horizontal movement to trigger the drag
touchMove(
- instrumentation, downTime, SystemClock.uptimeMillis(),
- DRAG_DURATION_MS, dragStart, dragMiddle
+ instrumentation,
+ downTime,
+ SystemClock.uptimeMillis(),
+ DRAG_DURATION_MS,
+ dragStart,
+ dragMiddle
)
touchMove(
- instrumentation, downTime, SystemClock.uptimeMillis(),
- DRAG_DURATION_MS, dragMiddle, dragEnd
+ instrumentation,
+ downTime,
+ SystemClock.uptimeMillis(),
+ DRAG_DURATION_MS,
+ dragMiddle,
+ dragEnd
)
// Wait for a while to start splitting
SystemClock.sleep(TIMEOUT_MS)
touch(
- instrumentation, MotionEvent.ACTION_UP, downTime, SystemClock.uptimeMillis(),
- GESTURE_STEP_MS, dragEnd
+ instrumentation,
+ MotionEvent.ACTION_UP,
+ downTime,
+ SystemClock.uptimeMillis(),
+ GESTURE_STEP_MS,
+ dragEnd
)
SystemClock.sleep(TIMEOUT_MS)
}
@@ -194,9 +205,8 @@ internal object SplitScreenUtils {
duration: Long,
point: Point
) {
- val motionEvent = MotionEvent.obtain(
- downTime, eventTime, action, point.x.toFloat(), point.y.toFloat(), 0
- )
+ val motionEvent =
+ MotionEvent.obtain(downTime, eventTime, action, point.x.toFloat(), point.y.toFloat(), 0)
motionEvent.source = InputDevice.SOURCE_TOUCHSCREEN
instrumentation.uiAutomation.injectInputEvent(motionEvent, true)
motionEvent.recycle()
@@ -219,9 +229,15 @@ internal object SplitScreenUtils {
val stepY = (to.y.toFloat() - from.y.toFloat()) / steps.toFloat()
for (i in 1..steps) {
- val motionMove = MotionEvent.obtain(
- downTime, currentTime, MotionEvent.ACTION_MOVE, currentX, currentY, 0
- )
+ val motionMove =
+ MotionEvent.obtain(
+ downTime,
+ currentTime,
+ MotionEvent.ACTION_MOVE,
+ currentX,
+ currentY,
+ 0
+ )
motionMove.source = InputDevice.SOURCE_TOUCHSCREEN
instrumentation.uiAutomation.injectInputEvent(motionMove, true)
motionMove.recycle()
@@ -238,20 +254,14 @@ internal object SplitScreenUtils {
}
}
- fun longPress(
- instrumentation: Instrumentation,
- point: Point
- ) {
+ fun longPress(instrumentation: Instrumentation, point: Point) {
val downTime = SystemClock.uptimeMillis()
touch(instrumentation, MotionEvent.ACTION_DOWN, downTime, downTime, TIMEOUT_MS, point)
SystemClock.sleep(LONG_PRESS_TIME_MS)
touch(instrumentation, MotionEvent.ACTION_UP, downTime, downTime, TIMEOUT_MS, point)
}
- fun createShortcutOnHotseatIfNotExist(
- tapl: LauncherInstrumentation,
- appName: String
- ) {
+ fun createShortcutOnHotseatIfNotExist(tapl: LauncherInstrumentation, appName: String) {
tapl.workspace.deleteAppIcon(tapl.workspace.getHotseatAppIcon(0))
val allApps = tapl.workspace.switchToAllApps()
allApps.freeze()
@@ -262,18 +272,15 @@ internal object SplitScreenUtils {
}
}
- fun dragDividerToResizeAndWait(
- device: UiDevice,
- wmHelper: WindowManagerStateHelper
- ) {
- val displayBounds = wmHelper.currentState.layerState
- .displays.firstOrNull { !it.isVirtual }
- ?.layerStackSpace
- ?: error("Display not found")
+ fun dragDividerToResizeAndWait(device: UiDevice, wmHelper: WindowManagerStateHelper) {
+ val displayBounds =
+ wmHelper.currentState.layerState.displays.firstOrNull { !it.isVirtual }?.layerStackSpace
+ ?: error("Display not found")
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
dividerBar.drag(Point(displayBounds.width * 1 / 3, displayBounds.height * 2 / 3))
- wmHelper.StateSyncBuilder()
+ wmHelper
+ .StateSyncBuilder()
.withWindowSurfaceDisappeared(SPLIT_DECOR_MANAGER)
.waitForAndVerify()
}
@@ -284,28 +291,30 @@ internal object SplitScreenUtils {
dragToRight: Boolean,
dragToBottom: Boolean
) {
- val displayBounds = wmHelper.currentState.layerState
- .displays.firstOrNull { !it.isVirtual }
- ?.layerStackSpace
- ?: error("Display not found")
+ val displayBounds =
+ wmHelper.currentState.layerState.displays.firstOrNull { !it.isVirtual }?.layerStackSpace
+ ?: error("Display not found")
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
- dividerBar.drag(Point(
- if (dragToRight) {
- displayBounds.width * 4 / 5
- } else {
- displayBounds.width * 1 / 5
- },
- if (dragToBottom) {
- displayBounds.height * 4 / 5
- } else {
- displayBounds.height * 1 / 5
- }))
+ dividerBar.drag(
+ Point(
+ if (dragToRight) {
+ displayBounds.width * 4 / 5
+ } else {
+ displayBounds.width * 1 / 5
+ },
+ if (dragToBottom) {
+ displayBounds.height * 4 / 5
+ } else {
+ displayBounds.height * 1 / 5
+ }
+ )
+ )
}
fun doubleTapDividerToSwitch(device: UiDevice) {
val dividerBar = device.wait(Until.findObject(dividerBarSelector), TIMEOUT_MS)
- val interval = (ViewConfiguration.getDoubleTapTimeout() +
- ViewConfiguration.getDoubleTapMinTime()) / 2
+ val interval =
+ (ViewConfiguration.getDoubleTapTimeout() + ViewConfiguration.getDoubleTapMinTime()) / 2
dividerBar.click()
SystemClock.sleep(interval.toLong())
dividerBar.click()
@@ -318,16 +327,22 @@ internal object SplitScreenUtils {
destinationApp: IComponentNameMatcher,
) {
// Copy text from sourceApp
- val textView = device.wait(Until.findObject(
- By.res(sourceApp.packageName, "SplitScreenTest")), TIMEOUT_MS)
+ val textView =
+ device.wait(
+ Until.findObject(By.res(sourceApp.packageName, "SplitScreenTest")),
+ TIMEOUT_MS
+ )
longPress(instrumentation, textView.visibleCenter)
val copyBtn = device.wait(Until.findObject(By.text("Copy")), TIMEOUT_MS)
copyBtn.click()
// Paste text to destinationApp
- val editText = device.wait(Until.findObject(
- By.res(destinationApp.packageName, "plain_text_input")), TIMEOUT_MS)
+ val editText =
+ device.wait(
+ Until.findObject(By.res(destinationApp.packageName, "plain_text_input")),
+ TIMEOUT_MS
+ )
longPress(instrumentation, editText.visibleCenter)
val pasteBtn = device.wait(Until.findObject(By.text("Paste")), TIMEOUT_MS)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
index 274a58c136c8..2ecf81931e4a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromAnotherApp.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.IwTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.WindowManagerPolicyConstants
import androidx.test.filters.RequiresDevice
@@ -55,9 +54,7 @@ class SwitchBackToSplitFromAnotherApp(testSpec: FlickerTestParameter) : SplitScr
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
thirdApp.launchViaIntent(wmHelper)
- wmHelper.StateSyncBuilder()
- .withWindowSurfaceAppeared(thirdApp)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withWindowSurfaceAppeared(thirdApp).waitForAndVerify()
}
transitions {
tapl.launchedAppState.quickSwitchToPreviousApp()
@@ -74,9 +71,7 @@ class SwitchBackToSplitFromAnotherApp(testSpec: FlickerTestParameter) : SplitScr
@Test
fun splitScreenDividerBecomesVisible() = testSpec.splitScreenDividerBecomesVisible()
- @Presubmit
- @Test
- fun primaryAppLayerBecomesVisible() = testSpec.layerBecomesVisible(primaryApp)
+ @Presubmit @Test fun primaryAppLayerBecomesVisible() = testSpec.layerBecomesVisible(primaryApp)
@Presubmit
@Test
@@ -84,13 +79,21 @@ class SwitchBackToSplitFromAnotherApp(testSpec: FlickerTestParameter) : SplitScr
@Presubmit
@Test
- fun primaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- primaryApp, landscapePosLeft = tapl.isTablet, portraitPosTop = false)
+ fun primaryAppBoundsIsVisibleAtEnd() =
+ testSpec.splitAppLayerBoundsIsVisibleAtEnd(
+ primaryApp,
+ landscapePosLeft = tapl.isTablet,
+ portraitPosTop = false
+ )
@Presubmit
@Test
- fun secondaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- secondaryApp, landscapePosLeft = !tapl.isTablet, portraitPosTop = true)
+ fun secondaryAppBoundsIsVisibleAtEnd() =
+ testSpec.splitAppLayerBoundsIsVisibleAtEnd(
+ secondaryApp,
+ landscapePosLeft = !tapl.isTablet,
+ portraitPosTop = true
+ )
@Presubmit
@Test
@@ -101,67 +104,60 @@ class SwitchBackToSplitFromAnotherApp(testSpec: FlickerTestParameter) : SplitScr
fun secondaryAppWindowBecomesVisible() = testSpec.appWindowBecomesVisible(secondaryApp)
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun entireScreenCovered() =
super.entireScreenCovered()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarLayerIsVisibleAtStartAndEnd() =
- super.navBarLayerIsVisibleAtStartAndEnd()
+ override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarLayerPositionAtStartAndEnd() =
- super.navBarLayerPositionAtStartAndEnd()
+ override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarWindowIsAlwaysVisible() =
- super.navBarWindowIsAlwaysVisible()
+ override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun statusBarLayerIsVisibleAtStartAndEnd() =
super.statusBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun statusBarWindowIsAlwaysVisible() =
- super.statusBarWindowIsAlwaysVisible()
+ override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() =
- super.taskBarLayerIsVisibleAtStartAndEnd()
+ override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun taskBarWindowIsAlwaysVisible() =
- super.taskBarWindowIsAlwaysVisible()
+ override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
@@ -170,10 +166,12 @@ class SwitchBackToSplitFromAnotherApp(testSpec: FlickerTestParameter) : SplitScr
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
- // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
- supportedNavigationModes =
- listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY))
+ return FlickerTestParameterFactory.getInstance()
+ .getConfigNonRotationTests(
+ // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
+ supportedNavigationModes =
+ listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY)
+ )
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
index 3da4a943af4e..384489d99de3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromHome.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.IwTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.WindowManagerPolicyConstants
import androidx.test.filters.RequiresDevice
@@ -54,9 +53,7 @@ class SwitchBackToSplitFromHome(testSpec: FlickerTestParameter) : SplitScreenBas
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
tapl.goHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
}
transitions {
tapl.workspace.quickSwitchToPreviousApp()
@@ -73,9 +70,7 @@ class SwitchBackToSplitFromHome(testSpec: FlickerTestParameter) : SplitScreenBas
@Test
fun splitScreenDividerBecomesVisible() = testSpec.splitScreenDividerBecomesVisible()
- @Presubmit
- @Test
- fun primaryAppLayerBecomesVisible() = testSpec.layerBecomesVisible(primaryApp)
+ @Presubmit @Test fun primaryAppLayerBecomesVisible() = testSpec.layerBecomesVisible(primaryApp)
@Presubmit
@Test
@@ -83,13 +78,21 @@ class SwitchBackToSplitFromHome(testSpec: FlickerTestParameter) : SplitScreenBas
@Presubmit
@Test
- fun primaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- primaryApp, landscapePosLeft = tapl.isTablet, portraitPosTop = false)
+ fun primaryAppBoundsIsVisibleAtEnd() =
+ testSpec.splitAppLayerBoundsIsVisibleAtEnd(
+ primaryApp,
+ landscapePosLeft = tapl.isTablet,
+ portraitPosTop = false
+ )
@Presubmit
@Test
- fun secondaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- secondaryApp, landscapePosLeft = !tapl.isTablet, portraitPosTop = true)
+ fun secondaryAppBoundsIsVisibleAtEnd() =
+ testSpec.splitAppLayerBoundsIsVisibleAtEnd(
+ secondaryApp,
+ landscapePosLeft = !tapl.isTablet,
+ portraitPosTop = true
+ )
@Presubmit
@Test
@@ -100,67 +103,60 @@ class SwitchBackToSplitFromHome(testSpec: FlickerTestParameter) : SplitScreenBas
fun secondaryAppWindowBecomesVisible() = testSpec.appWindowBecomesVisible(secondaryApp)
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun entireScreenCovered() =
super.entireScreenCovered()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarLayerIsVisibleAtStartAndEnd() =
- super.navBarLayerIsVisibleAtStartAndEnd()
+ override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarLayerPositionAtStartAndEnd() =
- super.navBarLayerPositionAtStartAndEnd()
+ override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarWindowIsAlwaysVisible() =
- super.navBarWindowIsAlwaysVisible()
+ override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun statusBarLayerIsVisibleAtStartAndEnd() =
super.statusBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun statusBarWindowIsAlwaysVisible() =
- super.statusBarWindowIsAlwaysVisible()
+ override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() =
- super.taskBarLayerIsVisibleAtStartAndEnd()
+ override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun taskBarWindowIsAlwaysVisible() =
- super.taskBarWindowIsAlwaysVisible()
+ override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
@@ -169,10 +165,12 @@ class SwitchBackToSplitFromHome(testSpec: FlickerTestParameter) : SplitScreenBas
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
- // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
- supportedNavigationModes =
- listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY))
+ return FlickerTestParameterFactory.getInstance()
+ .getConfigNonRotationTests(
+ // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
+ supportedNavigationModes =
+ listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY)
+ )
}
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
index f87d2951f265..04ebbf527b3d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/splitscreen/SwitchBackToSplitFromRecent.kt
@@ -17,7 +17,6 @@
package com.android.wm.shell.flicker.splitscreen
import android.platform.test.annotations.IwTest
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.view.WindowManagerPolicyConstants
import androidx.test.filters.RequiresDevice
@@ -54,14 +53,10 @@ class SwitchBackToSplitFromRecent(testSpec: FlickerTestParameter) : SplitScreenB
SplitScreenUtils.enterSplit(wmHelper, tapl, primaryApp, secondaryApp)
tapl.goHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
}
transitions {
- tapl.workspace.switchToOverview()
- .currentTask
- .open()
+ tapl.workspace.switchToOverview().currentTask.open()
SplitScreenUtils.waitForSplitComplete(wmHelper, primaryApp, secondaryApp)
}
}
@@ -75,9 +70,7 @@ class SwitchBackToSplitFromRecent(testSpec: FlickerTestParameter) : SplitScreenB
@Test
fun splitScreenDividerBecomesVisible() = testSpec.splitScreenDividerBecomesVisible()
- @Presubmit
- @Test
- fun primaryAppLayerBecomesVisible() = testSpec.layerBecomesVisible(primaryApp)
+ @Presubmit @Test fun primaryAppLayerBecomesVisible() = testSpec.layerBecomesVisible(primaryApp)
@Presubmit
@Test
@@ -85,13 +78,21 @@ class SwitchBackToSplitFromRecent(testSpec: FlickerTestParameter) : SplitScreenB
@Presubmit
@Test
- fun primaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- primaryApp, landscapePosLeft = tapl.isTablet, portraitPosTop = false)
+ fun primaryAppBoundsIsVisibleAtEnd() =
+ testSpec.splitAppLayerBoundsIsVisibleAtEnd(
+ primaryApp,
+ landscapePosLeft = tapl.isTablet,
+ portraitPosTop = false
+ )
@Presubmit
@Test
- fun secondaryAppBoundsIsVisibleAtEnd() = testSpec.splitAppLayerBoundsIsVisibleAtEnd(
- secondaryApp, landscapePosLeft = !tapl.isTablet, portraitPosTop = true)
+ fun secondaryAppBoundsIsVisibleAtEnd() =
+ testSpec.splitAppLayerBoundsIsVisibleAtEnd(
+ secondaryApp,
+ landscapePosLeft = !tapl.isTablet,
+ portraitPosTop = true
+ )
@Presubmit
@Test
@@ -102,67 +103,60 @@ class SwitchBackToSplitFromRecent(testSpec: FlickerTestParameter) : SplitScreenB
fun secondaryAppWindowBecomesVisible() = testSpec.appWindowBecomesVisible(secondaryApp)
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun entireScreenCovered() =
super.entireScreenCovered()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarLayerIsVisibleAtStartAndEnd() =
- super.navBarLayerIsVisibleAtStartAndEnd()
+ override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarLayerPositionAtStartAndEnd() =
- super.navBarLayerPositionAtStartAndEnd()
+ override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun navBarWindowIsAlwaysVisible() =
- super.navBarWindowIsAlwaysVisible()
+ override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun statusBarLayerIsVisibleAtStartAndEnd() =
super.statusBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun statusBarWindowIsAlwaysVisible() =
- super.statusBarWindowIsAlwaysVisible()
+ override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() =
- super.taskBarLayerIsVisibleAtStartAndEnd()
+ override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
- override fun taskBarWindowIsAlwaysVisible() =
- super.taskBarWindowIsAlwaysVisible()
+ override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
+ @Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
@@ -171,10 +165,12 @@ class SwitchBackToSplitFromRecent(testSpec: FlickerTestParameter) : SplitScreenB
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests(
- // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
- supportedNavigationModes =
- listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY))
+ return FlickerTestParameterFactory.getInstance()
+ .getConfigNonRotationTests(
+ // TODO(b/176061063):The 3 buttons of nav bar do not exist in the hierarchy.
+ supportedNavigationModes =
+ listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY)
+ )
}
}
}
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 283a41a81057..57815370e2ba 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -28,11 +28,13 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Locale;
import java.util.Objects;
import java.util.Set;
@@ -622,6 +624,58 @@ public final class MediaRoute2Info implements Parcelable {
return true;
}
+ /**
+ * Dumps the current state of the object to the given {@code pw} as a human-readable string.
+ *
+ * <p> Used in the context of dumpsys. </p>
+ *
+ * @hide
+ */
+ public void dump(@NonNull PrintWriter pw, @NonNull String prefix) {
+ pw.println(prefix + "MediaRoute2Info");
+
+ String indent = prefix + " ";
+
+ pw.println(indent + "mId=" + mId);
+ pw.println(indent + "mName=" + mName);
+ pw.println(indent + "mFeatures=" + mFeatures);
+ pw.println(indent + "mIsSystem=" + mIsSystem);
+ pw.println(indent + "mIconUri=" + mIconUri);
+ pw.println(indent + "mDescription=" + mDescription);
+ pw.println(indent + "mConnectionState=" + mConnectionState);
+ pw.println(indent + "mClientPackageName=" + mClientPackageName);
+ pw.println(indent + "mPackageName=" + mPackageName);
+
+ dumpVolume(pw, indent);
+
+ pw.println(indent + "mAddress=" + mAddress);
+ pw.println(indent + "mDeduplicationIds=" + mDeduplicationIds);
+ pw.println(indent + "mExtras=" + mExtras);
+ pw.println(indent + "mProviderId=" + mProviderId);
+ }
+
+ private void dumpVolume(@NonNull PrintWriter pw, @NonNull String prefix) {
+ String volumeHandlingName;
+
+ switch (mVolumeHandling) {
+ case PLAYBACK_VOLUME_FIXED:
+ volumeHandlingName = "FIXED";
+ break;
+ case PLAYBACK_VOLUME_VARIABLE:
+ volumeHandlingName = "VARIABLE";
+ break;
+ default:
+ volumeHandlingName = "UNKNOWN";
+ break;
+ }
+
+ String volume = String.format(Locale.US,
+ "volume(current=%d, max=%d, handling=%s(%d))",
+ mVolume, mVolumeMax, volumeHandlingName, mVolumeHandling);
+
+ pw.println(prefix + volume);
+ }
+
@Override
public boolean equals(Object obj) {
if (this == obj) {
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
index 4fb575b0ab09..9818ee78b2b1 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceActivity.java
@@ -45,6 +45,7 @@ import static java.util.Objects.requireNonNull;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.companion.AssociationInfo;
import android.companion.AssociationRequest;
import android.companion.CompanionDeviceManager;
@@ -81,6 +82,7 @@ import java.util.List;
* A CompanionDevice activity response for showing the available
* nearby devices to be associated with.
*/
+@SuppressLint("LongLogTag")
public class CompanionDeviceActivity extends FragmentActivity implements
CompanionVendorHelperDialogFragment.CompanionVendorHelperDialogListener {
private static final boolean DEBUG = false;
@@ -94,6 +96,7 @@ public class CompanionDeviceActivity extends FragmentActivity implements
private static final String EXTRA_APPLICATION_CALLBACK = "application_callback";
private static final String EXTRA_ASSOCIATION_REQUEST = "association_request";
private static final String EXTRA_RESULT_RECEIVER = "result_receiver";
+ private static final String EXTRA_FORCE_CANCEL_CONFIRMATION = "cancel_confirmation";
private static final String FRAGMENT_DIALOG_TAG = "fragment_dialog";
@@ -162,6 +165,12 @@ public class CompanionDeviceActivity extends FragmentActivity implements
@Override
public void onCreate(Bundle savedInstanceState) {
if (DEBUG) Log.d(TAG, "onCreate()");
+ boolean forceCancelDialog = getIntent().getBooleanExtra("cancel_confirmation", false);
+ // Must handle the force cancel request in onNewIntent.
+ if (forceCancelDialog) {
+ Log.i(TAG, "The confirmation does not exist, skipping the cancel request");
+ finish();
+ }
super.onCreate(savedInstanceState);
getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
@@ -195,10 +204,23 @@ public class CompanionDeviceActivity extends FragmentActivity implements
@Override
protected void onNewIntent(Intent intent) {
+ // Force cancels the CDM dialog if this activity receives another intent with
+ // EXTRA_FORCE_CANCEL_CONFIRMATION.
+ boolean forCancelDialog = intent.getBooleanExtra(EXTRA_FORCE_CANCEL_CONFIRMATION, false);
+
+ if (forCancelDialog) {
+
+ Log.i(TAG, "Cancelling the user confirmation");
+
+ cancel(false, false);
+ return;
+ }
+
// Handle another incoming request (while we are not done with the original - mRequest -
// yet).
final AssociationRequest request = requireNonNull(
intent.getParcelableExtra(EXTRA_ASSOCIATION_REQUEST));
+
if (DEBUG) Log.d(TAG, "onNewIntent(), request=" + request);
// We can only "process" one request at a time.
diff --git a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
index 732e7340cf5a..75b0df5ac628 100644
--- a/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
+++ b/packages/CompanionDeviceManager/src/com/android/companiondevicemanager/CompanionDeviceDiscoveryService.java
@@ -29,6 +29,7 @@ import static java.util.Objects.requireNonNull;
import android.annotation.MainThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -68,6 +69,7 @@ import java.util.Objects;
/**
* A CompanionDevice service response for scanning nearby devices
*/
+@SuppressLint("LongLogTag")
public class CompanionDeviceDiscoveryService extends Service {
private static final boolean DEBUG = false;
private static final String TAG = "CDM_CompanionDeviceDiscoveryService";
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 9324e8f3babb..637ac1911a85 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -246,6 +246,16 @@
<string name="screenrecord_start_label">Start Recording?</string>
<!-- Message reminding the user that sensitive information may be captured during a screen recording [CHAR_LIMIT=NONE]-->
<string name="screenrecord_description">While recording, Android System can capture any sensitive information that\u2019s visible on your screen or played on your device. This includes passwords, payment info, photos, messages, and audio.</string>
+ <!-- Dropdown option to record the entire screen [CHAR_LIMIT=30]-->
+ <string name="screenrecord_option_entire_screen">Record entire screen</string>
+ <!-- Dropdown option to record a single app [CHAR_LIMIT=30]-->
+ <string name="screenrecord_option_single_app">Record a single app</string>
+ <!-- Message reminding the user that sensitive information may be captured during a full screen recording for the updated dialog that includes partial screen sharing option [CHAR_LIMIT=350]-->
+ <string name="screenrecord_warning_entire_screen">While you\'re recording, Android has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages, or other sensitive information.</string>
+ <!-- Message reminding the user that sensitive information may be captured during a single app screen recording for the updated dialog that includes partial screen sharing option [CHAR_LIMIT=350]-->
+ <string name="screenrecord_warning_single_app">While you\'re recording an app, Android has access to anything shown or played on that app. So be careful with passwords, payment details, messages, or other sensitive information.</string>
+ <!-- Button to start a screen recording in the updated screen record dialog that allows to select an app to record [CHAR LIMIT=50]-->
+ <string name="screenrecord_start_recording">Start recording</string>
<!-- Label for a switch to enable recording audio [CHAR LIMIT=NONE]-->
<string name="screenrecord_audio_label">Record audio</string>
<!-- Label for the option to record audio from the device [CHAR LIMIT=NONE]-->
@@ -958,7 +968,26 @@
<!-- Media projection permission dialog warning title. [CHAR LIMIT=NONE] -->
<string name="media_projection_dialog_title">Start recording or casting with <xliff:g id="app_seeking_permission" example="Hangouts">%s</xliff:g>?</string>
- <!-- Media projection permission dialog permanent grant check box. [CHAR LIMIT=NONE] -->
+ <!-- Media projection permission dialog title. [CHAR LIMIT=NONE] -->
+ <string name="media_projection_permission_dialog_title">Allow <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> to share or record?</string>
+
+ <!-- Media projection permission dropdown option for capturing the whole screen. [CHAR LIMIT=30] -->
+ <string name="media_projection_permission_dialog_option_entire_screen">Entire screen</string>
+
+ <!-- Media projection permission dropdown option for capturing single app. [CHAR LIMIT=30] -->
+ <string name="media_projection_permission_dialog_option_single_app">A single app</string>
+
+ <!-- Media projection permission warning for capturing the whole screen. [CHAR LIMIT=350] -->
+ <string name="media_projection_permission_dialog_warning_entire_screen">When you\'re sharing, recording, or casting, <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> has access to anything visible on your screen or played on your device. So be careful with passwords, payment details, messages, or other sensitive information.</string>
+
+ <!-- Media projection permission warning for capturing an app. [CHAR LIMIT=350] -->
+ <string name="media_projection_permission_dialog_warning_single_app">When you\'re sharing, recording, or casting an app, <xliff:g id="app_seeking_permission" example="Meet">%s</xliff:g> has access to anything shown or played on that app. So be careful with passwords, payment details, messages, or other sensitive information.</string>
+
+ <!-- Media projection permission button to continue with app selection or recording [CHAR LIMIT=60] -->
+ <string name="media_projection_permission_dialog_continue">Continue</string>
+
+ <!-- Title of the dialog that allows to select an app to share or record [CHAR LIMIT=NONE] -->
+ <string name="media_projection_permission_app_selector_title">Share or record an app</string>
<!-- The text to clear all notifications. [CHAR LIMIT=60] -->
<string name="clear_all_notifications_text">Clear all</string>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index e77c65079456..2b2b05ce2fbf 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -81,11 +81,6 @@ interface ISystemUiProxy {
*/
void stopScreenPinning() = 17;
- /*
- * Notifies that the swipe-to-home (recents animation) is finished.
- */
- void notifySwipeToHomeFinished() = 23;
-
/**
* Notifies that quickstep will switch to a new task
* @param rotation indicates which Surface.Rotation the gesture was started in
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SimpleMirrorWindowControl.java b/packages/SystemUI/src/com/android/systemui/accessibility/SimpleMirrorWindowControl.java
index 2ba2bb6edc18..ed6fbecd19fe 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SimpleMirrorWindowControl.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SimpleMirrorWindowControl.java
@@ -45,7 +45,7 @@ class SimpleMirrorWindowControl extends MirrorWindowControl implements View.OnCl
private boolean mShouldSetTouchStart;
@Nullable private MoveWindowTask mMoveWindowTask;
- private PointF mLastDrag = new PointF();
+ private final PointF mLastDrag = new PointF();
private final Handler mHandler;
SimpleMirrorWindowControl(Context context, Handler handler) {
@@ -92,8 +92,7 @@ class SimpleMirrorWindowControl extends MirrorWindowControl implements View.OnCl
}
private Point findOffset(View v, int moveFrameAmount) {
- final Point offset = mTmpPoint;
- offset.set(0, 0);
+ mTmpPoint.set(0, 0);
if (v.getId() == R.id.left_control) {
mTmpPoint.x = -moveFrameAmount;
} else if (v.getId() == R.id.up_control) {
@@ -184,7 +183,7 @@ class SimpleMirrorWindowControl extends MirrorWindowControl implements View.OnCl
private final int mYOffset;
private final Handler mHandler;
/** Time in milliseconds between successive task executions.*/
- private long mPeriod;
+ private final long mPeriod;
private boolean mCancel;
MoveWindowTask(@NonNull MirrorWindowDelegate windowDelegate, Handler handler, int xOffset,
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
index e3c04a379fe4..a6e767ca27ee 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java
@@ -104,7 +104,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
private final Context mContext;
private final Resources mResources;
private final Handler mHandler;
- private Rect mWindowBounds;
+ private final Rect mWindowBounds;
private final int mDisplayId;
@Surface.Rotation
@VisibleForTesting
@@ -193,11 +193,11 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider;
private final MagnificationGestureDetector mGestureDetector;
private final int mBounceEffectDuration;
- private Choreographer.FrameCallback mMirrorViewGeometryVsyncCallback;
+ private final Choreographer.FrameCallback mMirrorViewGeometryVsyncCallback;
private Locale mLocale;
private NumberFormat mPercentFormat;
private float mBounceEffectAnimationScale;
- private SysUiState mSysUiState;
+ private final SysUiState mSysUiState;
// Set it to true when the view is overlapped with the gesture insets at the bottom.
private boolean mOverlapWithGestureInsets;
private boolean mIsDragging;
@@ -215,7 +215,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
private boolean mEditSizeEnable = false;
@Nullable
- private MirrorWindowControl mMirrorWindowControl;
+ private final MirrorWindowControl mMirrorWindowControl;
WindowMagnificationController(
@UiContext Context context,
@@ -562,9 +562,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold
/** Returns the rotation degree change of two {@link Surface.Rotation} */
private int getDegreeFromRotation(@Surface.Rotation int newRotation,
@Surface.Rotation int oldRotation) {
- final int rotationDiff = oldRotation - newRotation;
- final int degree = (rotationDiff + 4) % 4 * 90;
- return degree;
+ return (oldRotation - newRotation + 4) % 4 * 90;
}
private void createMirrorWindow() {
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
index 38d9d0210378..17445d319b9c 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java
@@ -247,6 +247,13 @@ public class Flags {
public static final SysPropBooleanFlag SHOW_FLOATING_TASKS_AS_BUBBLES =
new SysPropBooleanFlag(1107, "persist.wm.debug.floating_tasks_as_bubbles", false);
+ @Keep
+ public static final SysPropBooleanFlag ENABLE_FLING_TO_DISMISS_BUBBLE =
+ new SysPropBooleanFlag(1108, "persist.wm.debug.fling_to_dismiss_bubble", true);
+ @Keep
+ public static final SysPropBooleanFlag ENABLE_FLING_TO_DISMISS_PIP =
+ new SysPropBooleanFlag(1109, "persist.wm.debug.fling_to_dismiss_pip", true);
+
// 1200 - predictive back
@Keep
public static final SysPropBooleanFlag WM_ENABLE_PREDICTIVE_BACK = new SysPropBooleanFlag(
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 0f1338e4e872..b26b42c802f4 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -57,7 +57,6 @@ import android.window.BackEvent;
import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.internal.policy.GestureNavigationSettingsObserver;
-import com.android.internal.util.LatencyTracker;
import com.android.systemui.R;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Background;
@@ -199,7 +198,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
private final Rect mNavBarOverlayExcludedBounds = new Rect();
private final Region mExcludeRegion = new Region();
private final Region mUnrestrictedExcludeRegion = new Region();
- private final LatencyTracker mLatencyTracker;
+ private final Provider<NavigationBarEdgePanel> mNavBarEdgePanelProvider;
private final Provider<BackGestureTfClassifierProvider>
mBackGestureTfClassifierProviderProvider;
private final FeatureFlags mFeatureFlags;
@@ -339,7 +338,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
IWindowManager windowManagerService,
Optional<Pip> pipOptional,
FalsingManager falsingManager,
- LatencyTracker latencyTracker,
+ Provider<NavigationBarEdgePanel> navigationBarEdgePanelProvider,
Provider<BackGestureTfClassifierProvider> backGestureTfClassifierProviderProvider,
FeatureFlags featureFlags) {
super(broadcastDispatcher);
@@ -358,7 +357,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
mWindowManagerService = windowManagerService;
mPipOptional = pipOptional;
mFalsingManager = falsingManager;
- mLatencyTracker = latencyTracker;
+ mNavBarEdgePanelProvider = navigationBarEdgePanelProvider;
mBackGestureTfClassifierProviderProvider = backGestureTfClassifierProviderProvider;
mFeatureFlags = featureFlags;
mLastReportedConfig.setTo(mContext.getResources().getConfiguration());
@@ -583,8 +582,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
setEdgeBackPlugin(
mBackPanelControllerFactory.create(mContext));
} else {
- setEdgeBackPlugin(
- new NavigationBarEdgePanel(mContext, mLatencyTracker));
+ setEdgeBackPlugin(mNavBarEdgePanelProvider.get());
}
}
@@ -1091,7 +1089,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
private final IWindowManager mWindowManagerService;
private final Optional<Pip> mPipOptional;
private final FalsingManager mFalsingManager;
- private final LatencyTracker mLatencyTracker;
+ private final Provider<NavigationBarEdgePanel> mNavBarEdgePanelProvider;
private final Provider<BackGestureTfClassifierProvider>
mBackGestureTfClassifierProviderProvider;
private final FeatureFlags mFeatureFlags;
@@ -1111,7 +1109,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
IWindowManager windowManagerService,
Optional<Pip> pipOptional,
FalsingManager falsingManager,
- LatencyTracker latencyTracker,
+ Provider<NavigationBarEdgePanel> navBarEdgePanelProvider,
Provider<BackGestureTfClassifierProvider>
backGestureTfClassifierProviderProvider,
FeatureFlags featureFlags) {
@@ -1129,7 +1127,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
mWindowManagerService = windowManagerService;
mPipOptional = pipOptional;
mFalsingManager = falsingManager;
- mLatencyTracker = latencyTracker;
+ mNavBarEdgePanelProvider = navBarEdgePanelProvider;
mBackGestureTfClassifierProviderProvider = backGestureTfClassifierProviderProvider;
mFeatureFlags = featureFlags;
}
@@ -1152,7 +1150,7 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
mWindowManagerService,
mPipOptional,
mFalsingManager,
- mLatencyTracker,
+ mNavBarEdgePanelProvider,
mBackGestureTfClassifierProviderProvider,
mFeatureFlags);
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
index 24efc762b39b..1230708d780a 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/NavigationBarEdgePanel.java
@@ -52,9 +52,9 @@ import androidx.dynamicanimation.animation.SpringForce;
import com.android.internal.util.LatencyTracker;
import com.android.settingslib.Utils;
-import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
+import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.plugins.NavigationEdgeBackPlugin;
import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
import com.android.systemui.statusbar.VibratorHelper;
@@ -62,6 +62,8 @@ import com.android.systemui.statusbar.VibratorHelper;
import java.io.PrintWriter;
import java.util.concurrent.Executor;
+import javax.inject.Inject;
+
public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPlugin {
private static final String TAG = "NavigationBarEdgePanel";
@@ -282,11 +284,16 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
};
private BackCallback mBackCallback;
- public NavigationBarEdgePanel(Context context, LatencyTracker latencyTracker) {
+ @Inject
+ public NavigationBarEdgePanel(
+ Context context,
+ LatencyTracker latencyTracker,
+ VibratorHelper vibratorHelper,
+ @Background Executor backgroundExecutor) {
super(context);
mWindowManager = context.getSystemService(WindowManager.class);
- mVibratorHelper = Dependency.get(VibratorHelper.class);
+ mVibratorHelper = vibratorHelper;
mDensity = context.getResources().getDisplayMetrics().density;
@@ -358,7 +365,6 @@ public class NavigationBarEdgePanel extends View implements NavigationEdgeBackPl
setVisibility(GONE);
- Executor backgroundExecutor = Dependency.get(Dependency.BACKGROUND_EXECUTOR);
boolean isPrimaryDisplay = mContext.getDisplayId() == DEFAULT_DISPLAY;
mRegionSamplingHelper = new RegionSamplingHelper(this,
new RegionSamplingHelper.SamplingCallback() {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index b3e6f8ab3de6..7a44058a46c7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -60,6 +60,7 @@ import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder;
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.BrightnessMirrorController;
@@ -82,7 +83,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private static final String EXTRA_VISIBLE = "visible";
private final Rect mQsBounds = new Rect();
- private final StatusBarStateController mStatusBarStateController;
+ private final SysuiStatusBarStateController mStatusBarStateController;
private final FalsingManager mFalsingManager;
private final KeyguardBypassController mBypassController;
private boolean mQsExpanded;
@@ -159,7 +160,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
* Progress of pull down from the center of the lock screen.
* @see com.android.systemui.statusbar.LockscreenShadeTransitionController
*/
- private float mFullShadeProgress;
+ private float mLockscreenToShadeProgress;
private boolean mOverScrolling;
@@ -177,7 +178,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
@Inject
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
QSTileHost qsTileHost,
- StatusBarStateController statusBarStateController, CommandQueue commandQueue,
+ SysuiStatusBarStateController statusBarStateController, CommandQueue commandQueue,
@Named(QS_PANEL) MediaHost qsMediaHost,
@Named(QUICK_QS_PANEL) MediaHost qqsMediaHost,
KeyguardBypassController keyguardBypassController,
@@ -442,20 +443,19 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
}
private void updateQsState() {
- final boolean expanded = mQsExpanded || mInSplitShade;
- final boolean expandVisually = expanded || mStackScrollerOverscrolling
+ final boolean expandVisually = mQsExpanded || mStackScrollerOverscrolling
|| mHeaderAnimating;
- mQSPanelController.setExpanded(expanded);
+ mQSPanelController.setExpanded(mQsExpanded);
boolean keyguardShowing = isKeyguardState();
- mHeader.setVisibility((expanded || !keyguardShowing || mHeaderAnimating
+ mHeader.setVisibility((mQsExpanded || !keyguardShowing || mHeaderAnimating
|| mShowCollapsedOnKeyguard)
? View.VISIBLE
: View.INVISIBLE);
mHeader.setExpanded((keyguardShowing && !mHeaderAnimating && !mShowCollapsedOnKeyguard)
- || (expanded && !mStackScrollerOverscrolling), mQuickQSPanelController);
+ || (mQsExpanded && !mStackScrollerOverscrolling), mQuickQSPanelController);
boolean qsPanelVisible = !mQsDisabled && expandVisually;
- boolean footerVisible = qsPanelVisible && (expanded || !keyguardShowing || mHeaderAnimating
- || mShowCollapsedOnKeyguard);
+ boolean footerVisible = qsPanelVisible && (mQsExpanded || !keyguardShowing
+ || mHeaderAnimating || mShowCollapsedOnKeyguard);
mFooter.setVisibility(footerVisible ? View.VISIBLE : View.INVISIBLE);
if (mQSFooterActionController != null) {
mQSFooterActionController.setVisible(footerVisible);
@@ -463,7 +463,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mQSFooterActionsViewModel.onVisibilityChangeRequested(footerVisible);
}
mFooter.setExpanded((keyguardShowing && !mHeaderAnimating && !mShowCollapsedOnKeyguard)
- || (expanded && !mStackScrollerOverscrolling));
+ || (mQsExpanded && !mStackScrollerOverscrolling));
mQSPanelController.setVisibility(qsPanelVisible ? View.VISIBLE : View.INVISIBLE);
if (DEBUG) {
Log.d(TAG, "Footer: " + footerVisible + ", QS Panel: " + qsPanelVisible);
@@ -586,7 +586,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mTransitioningToFullShade = isTransitioningToFullShade;
updateShowCollapsedOnKeyguard();
}
- mFullShadeProgress = qsTransitionFraction;
+ mLockscreenToShadeProgress = qsTransitionFraction;
setQsExpansion(mLastQSExpansion, mLastPanelFraction, mLastHeaderTranslation,
isTransitioningToFullShade ? qsSquishinessFraction : mSquishinessFraction);
}
@@ -710,10 +710,13 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
}
if (mInSplitShade) {
// Large screens in landscape.
- if (mTransitioningToFullShade || isKeyguardState()) {
+ // Need to check upcoming state as for unlocked -> AOD transition current state is
+ // not updated yet, but we're transitioning and UI should already follow KEYGUARD state
+ if (mTransitioningToFullShade || mStatusBarStateController.getCurrentOrUpcomingState()
+ == StatusBarState.KEYGUARD) {
// Always use "mFullShadeProgress" on keyguard, because
// "panelExpansionFractions" is always 1 on keyguard split shade.
- return mFullShadeProgress;
+ return mLockscreenToShadeProgress;
} else {
return panelExpansionFraction;
}
@@ -722,7 +725,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
if (mTransitioningToFullShade) {
// Only use this value during the standard lock screen shade expansion. During the
// "quick" expansion from top, this value is 0.
- return mFullShadeProgress;
+ return mLockscreenToShadeProgress;
} else {
return panelExpansionFraction;
}
@@ -930,7 +933,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
indentingPw.println("mLastHeaderTranslation: " + mLastHeaderTranslation);
indentingPw.println("mInSplitShade: " + mInSplitShade);
indentingPw.println("mTransitioningToFullShade: " + mTransitioningToFullShade);
- indentingPw.println("mFullShadeProgress: " + mFullShadeProgress);
+ indentingPw.println("mLockscreenToShadeProgress: " + mLockscreenToShadeProgress);
indentingPw.println("mOverScrolling: " + mOverScrolling);
indentingPw.println("isCustomizing: " + mQSCustomizerController.isCustomizing());
View view = getView();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 7e2a5c51786d..899e57d7d0ae 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -342,14 +342,6 @@ public class OverviewProxyService extends CurrentUserTracker implements
}
@Override
- public void notifySwipeToHomeFinished() {
- verifyCallerAndClearCallingIdentity("notifySwipeToHomeFinished", () ->
- mPipOptional.ifPresent(
- pip -> pip.setPinnedStackAnimationType(
- PipAnimationController.ANIM_TYPE_ALPHA)));
- }
-
- @Override
public void notifySwipeUpGestureStarted() {
verifyCallerAndClearCallingIdentityPostMain("notifySwipeUpGestureStarted", () ->
notifySwipeUpGestureStartedInternal());
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
index a22fda7f9a47..6e9f859c202b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
@@ -25,6 +25,7 @@ import android.os.Handler;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
@@ -76,6 +77,12 @@ public class BrightnessDialog extends Activity {
FrameLayout frame = findViewById(R.id.brightness_mirror_container);
// The brightness mirror container is INVISIBLE by default.
frame.setVisibility(View.VISIBLE);
+ ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) frame.getLayoutParams();
+ int horizontalMargin =
+ getResources().getDimensionPixelSize(R.dimen.notification_side_paddings);
+ lp.leftMargin = horizontalMargin;
+ lp.rightMargin = horizontalMargin;
+ frame.setLayoutParams(lp);
BrightnessSliderController controller = mToggleSliderFactory.create(this, frame);
controller.init();
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index d7e86b6e2919..7254e090e32f 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -430,6 +430,7 @@ public final class NotificationPanelViewController extends PanelViewController {
/**
* Determines if QS should be already expanded when expanding shade.
* Used for split shade, two finger gesture as well as accessibility shortcut to QS.
+ * It needs to be set when movement starts as it resets at the end of expansion/collapse.
*/
@VisibleForTesting
boolean mQsExpandImmediate;
@@ -1737,8 +1738,10 @@ public final class NotificationPanelViewController extends PanelViewController {
}
private void setQsExpandImmediate(boolean expandImmediate) {
- mQsExpandImmediate = expandImmediate;
- mPanelEventsEmitter.notifyExpandImmediateChange(expandImmediate);
+ if (expandImmediate != mQsExpandImmediate) {
+ mQsExpandImmediate = expandImmediate;
+ mPanelEventsEmitter.notifyExpandImmediateChange(expandImmediate);
+ }
}
private void setShowShelfOnly(boolean shelfOnly) {
@@ -2479,17 +2482,23 @@ public final class NotificationPanelViewController extends PanelViewController {
mDepthController.setQsPanelExpansion(qsExpansionFraction);
mStatusBarKeyguardViewManager.setQsExpansion(qsExpansionFraction);
- // updateQsExpansion will get called whenever mTransitionToFullShadeProgress or
- // mLockscreenShadeTransitionController.getDragProgress change.
- // When in lockscreen, getDragProgress indicates the true expanded fraction of QS
- float shadeExpandedFraction = mTransitioningToFullShadeProgress > 0
- ? mLockscreenShadeTransitionController.getQSDragProgress()
+ float shadeExpandedFraction = isOnKeyguard()
+ ? getLockscreenShadeDragProgress()
: getExpandedFraction();
mLargeScreenShadeHeaderController.setShadeExpandedFraction(shadeExpandedFraction);
mLargeScreenShadeHeaderController.setQsExpandedFraction(qsExpansionFraction);
mLargeScreenShadeHeaderController.setQsVisible(mQsVisible);
}
+ private float getLockscreenShadeDragProgress() {
+ // mTransitioningToFullShadeProgress > 0 means we're doing regular lockscreen to shade
+ // transition. If that's not the case we should follow QS expansion fraction for when
+ // user is pulling from the same top to go directly to expanded QS
+ return mTransitioningToFullShadeProgress > 0
+ ? mLockscreenShadeTransitionController.getQSDragProgress()
+ : computeQsExpansionFraction();
+ }
+
private void onStackYChanged(boolean shouldAnimate) {
if (mQs != null) {
if (shouldAnimate) {
@@ -3124,26 +3133,24 @@ public final class NotificationPanelViewController extends PanelViewController {
}
if (mQsExpandImmediate || (mQsExpanded && !mQsTracking && mQsExpansionAnimator == null
&& !mQsExpansionFromOverscroll)) {
- float t;
- if (mKeyguardShowing) {
-
+ float qsExpansionFraction;
+ if (mSplitShadeEnabled) {
+ qsExpansionFraction = 1;
+ } else if (mKeyguardShowing) {
// On Keyguard, interpolate the QS expansion linearly to the panel expansion
- t = expandedHeight / (getMaxPanelHeight());
+ qsExpansionFraction = expandedHeight / (getMaxPanelHeight());
} else {
// In Shade, interpolate linearly such that QS is closed whenever panel height is
// minimum QS expansion + minStackHeight
- float
- panelHeightQsCollapsed =
+ float panelHeightQsCollapsed =
mNotificationStackScrollLayoutController.getIntrinsicPadding()
+ mNotificationStackScrollLayoutController.getLayoutMinHeight();
float panelHeightQsExpanded = calculatePanelHeightQsExpanded();
- t =
- (expandedHeight - panelHeightQsCollapsed) / (panelHeightQsExpanded
- - panelHeightQsCollapsed);
+ qsExpansionFraction = (expandedHeight - panelHeightQsCollapsed)
+ / (panelHeightQsExpanded - panelHeightQsCollapsed);
}
- float
- targetHeight =
- mQsMinExpansionHeight + t * (mQsMaxExpansionHeight - mQsMinExpansionHeight);
+ float targetHeight = mQsMinExpansionHeight
+ + qsExpansionFraction * (mQsMaxExpansionHeight - mQsMinExpansionHeight);
setQsExpansion(targetHeight);
}
updateExpandedHeight(expandedHeight);
@@ -3329,7 +3336,11 @@ public final class NotificationPanelViewController extends PanelViewController {
} else {
setListening(true);
}
- setQsExpandImmediate(false);
+ if (mBarState != SHADE) {
+ // updating qsExpandImmediate is done in onPanelStateChanged for unlocked shade but
+ // on keyguard panel state is always OPEN so we need to have that extra update
+ setQsExpandImmediate(false);
+ }
setShowShelfOnly(false);
mTwoFingerQsExpandPossible = false;
updateTrackingHeadsUp(null);
@@ -4678,6 +4689,11 @@ public final class NotificationPanelViewController extends PanelViewController {
}
}
} else {
+ // this else branch means we are doing one of:
+ // - from KEYGUARD and SHADE (but not expanded shade)
+ // - from SHADE to KEYGUARD
+ // - from SHADE_LOCKED to SHADE
+ // - getting notified again about the current SHADE or KEYGUARD state
final boolean animatingUnlockedShadeToKeyguard = oldState == SHADE
&& statusBarState == KEYGUARD
&& mScreenOffAnimationController.isKeyguardShowDelayed();
@@ -4749,9 +4765,7 @@ public final class NotificationPanelViewController extends PanelViewController {
@Override
public float getLockscreenShadeDragProgress() {
- return mTransitioningToFullShadeProgress > 0
- ? mLockscreenShadeTransitionController.getQSDragProgress()
- : computeQsExpansionFraction();
+ return NotificationPanelViewController.this.getLockscreenShadeDragProgress();
}
};
@@ -4988,6 +5002,7 @@ public final class NotificationPanelViewController extends PanelViewController {
updateQSExpansionEnabledAmbient();
if (state == STATE_OPEN && mCurrentPanelState != state) {
+ setQsExpandImmediate(false);
mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
}
if (state == STATE_OPENING) {
@@ -5000,6 +5015,7 @@ public final class NotificationPanelViewController extends PanelViewController {
mCentralSurfaces.makeExpandedVisible(false);
}
if (state == STATE_CLOSED) {
+ setQsExpandImmediate(false);
// Close the status bar in the next frame so we can show the end of the
// animation.
mView.post(mMaybeHideExpandedRunnable);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
index 8278b549a7a0..ccf6feca6992 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.kt
@@ -393,7 +393,7 @@ class HeadsUpCoordinator @Inject constructor(
val posted = mPostedEntries.compute(entry.key) { _, value ->
value?.also { update ->
update.wasUpdated = true
- update.shouldHeadsUpEver = update.shouldHeadsUpEver || shouldHeadsUpEver
+ update.shouldHeadsUpEver = shouldHeadsUpEver
update.shouldHeadsUpAgain = update.shouldHeadsUpAgain || shouldHeadsUpAgain
update.isAlerting = isAlerting
update.isBinding = isBinding
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
index bc172ce537f3..0b435fe9dcc6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
@@ -35,12 +35,12 @@ import com.android.systemui.statusbar.notification.row.ExpandableView;
* bounds change.
*/
public class NotificationSection {
- private @PriorityBucket int mBucket;
- private View mOwningView;
- private Rect mBounds = new Rect();
- private Rect mCurrentBounds = new Rect(-1, -1, -1, -1);
- private Rect mStartAnimationRect = new Rect();
- private Rect mEndAnimationRect = new Rect();
+ private @PriorityBucket final int mBucket;
+ private final View mOwningView;
+ private final Rect mBounds = new Rect();
+ private final Rect mCurrentBounds = new Rect(-1, -1, -1, -1);
+ private final Rect mStartAnimationRect = new Rect();
+ private final Rect mEndAnimationRect = new Rect();
private ObjectAnimator mTopAnimator = null;
private ObjectAnimator mBottomAnimator = null;
private ExpandableView mFirstVisibleChild;
@@ -277,7 +277,6 @@ public class NotificationSection {
}
}
}
- top = Math.max(minTopPosition, top);
ExpandableView lastView = getLastVisibleChild();
if (lastView != null) {
float finalTranslationY = ViewState.getFinalTranslationY(lastView);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 5fbaa515d5d7..e37750194368 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -135,7 +135,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private static final boolean SPEW = Log.isLoggable(TAG, Log.VERBOSE);
// Delay in milli-seconds before shade closes for clear all.
- private final int DELAY_BEFORE_SHADE_CLOSE = 200;
+ private static final int DELAY_BEFORE_SHADE_CLOSE = 200;
private boolean mShadeNeedsToClose = false;
private static final float RUBBER_BAND_FACTOR_NORMAL = 0.35f;
@@ -152,7 +152,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private static final int DISTANCE_BETWEEN_ADJACENT_SECTIONS_PX = 1;
private boolean mKeyguardBypassEnabled;
- private ExpandHelper mExpandHelper;
+ private final ExpandHelper mExpandHelper;
private NotificationSwipeHelper mSwipeHelper;
private int mCurrentStackHeight = Integer.MAX_VALUE;
private final Paint mBackgroundPaint = new Paint();
@@ -165,12 +165,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private VelocityTracker mVelocityTracker;
private OverScroller mScroller;
- /** Last Y position reported by {@link #mScroller}, used to calculate scroll delta. */
- private int mLastScrollerY;
- /**
- * True if the max position was set to a known position on the last call to {@link #mScroller}.
- */
- private boolean mIsScrollerBoundSet;
+
private Runnable mFinishScrollingCallback;
private int mTouchSlop;
private float mSlopMultiplier;
@@ -194,7 +189,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private int mContentHeight;
private float mIntrinsicContentHeight;
- private int mCollapsedSize;
private int mPaddingBetweenElements;
private int mMaxTopPadding;
private int mTopPadding;
@@ -210,15 +204,15 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private final StackScrollAlgorithm mStackScrollAlgorithm;
private final AmbientState mAmbientState;
- private GroupMembershipManager mGroupMembershipManager;
- private GroupExpansionManager mGroupExpansionManager;
- private HashSet<ExpandableView> mChildrenToAddAnimated = new HashSet<>();
- private ArrayList<View> mAddedHeadsUpChildren = new ArrayList<>();
- private ArrayList<ExpandableView> mChildrenToRemoveAnimated = new ArrayList<>();
- private ArrayList<ExpandableView> mChildrenChangingPositions = new ArrayList<>();
- private HashSet<View> mFromMoreCardAdditions = new HashSet<>();
- private ArrayList<AnimationEvent> mAnimationEvents = new ArrayList<>();
- private ArrayList<View> mSwipedOutViews = new ArrayList<>();
+ private final GroupMembershipManager mGroupMembershipManager;
+ private final GroupExpansionManager mGroupExpansionManager;
+ private final HashSet<ExpandableView> mChildrenToAddAnimated = new HashSet<>();
+ private final ArrayList<View> mAddedHeadsUpChildren = new ArrayList<>();
+ private final ArrayList<ExpandableView> mChildrenToRemoveAnimated = new ArrayList<>();
+ private final ArrayList<ExpandableView> mChildrenChangingPositions = new ArrayList<>();
+ private final HashSet<View> mFromMoreCardAdditions = new HashSet<>();
+ private final ArrayList<AnimationEvent> mAnimationEvents = new ArrayList<>();
+ private final ArrayList<View> mSwipedOutViews = new ArrayList<>();
private NotificationStackSizeCalculator mNotificationStackSizeCalculator;
private final StackStateAnimator mStateAnimator = new StackStateAnimator(this);
private boolean mAnimationsEnabled;
@@ -296,7 +290,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private boolean mDisallowDismissInThisMotion;
private boolean mDisallowScrollingInThisMotion;
private long mGoToFullShadeDelay;
- private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
+ private final ViewTreeObserver.OnPreDrawListener mChildrenUpdater
= new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
@@ -309,17 +303,16 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
};
private NotificationStackScrollLogger mLogger;
private CentralSurfaces mCentralSurfaces;
- private int[] mTempInt2 = new int[2];
+ private final int[] mTempInt2 = new int[2];
private boolean mGenerateChildOrderChangedEvent;
- private HashSet<Runnable> mAnimationFinishedRunnables = new HashSet<>();
- private HashSet<ExpandableView> mClearTransientViewsWhenFinished = new HashSet<>();
- private HashSet<Pair<ExpandableNotificationRow, Boolean>> mHeadsUpChangeAnimations
+ private final HashSet<Runnable> mAnimationFinishedRunnables = new HashSet<>();
+ private final HashSet<ExpandableView> mClearTransientViewsWhenFinished = new HashSet<>();
+ private final HashSet<Pair<ExpandableNotificationRow, Boolean>> mHeadsUpChangeAnimations
= new HashSet<>();
- private boolean mTrackingHeadsUp;
private boolean mForceNoOverlappingRendering;
private final ArrayList<Pair<ExpandableNotificationRow, Boolean>> mTmpList = new ArrayList<>();
private boolean mAnimationRunning;
- private ViewTreeObserver.OnPreDrawListener mRunningAnimationUpdater
+ private final ViewTreeObserver.OnPreDrawListener mRunningAnimationUpdater
= new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
@@ -327,21 +320,21 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
return true;
}
};
- private NotificationSection[] mSections;
+ private final NotificationSection[] mSections;
private boolean mAnimateNextBackgroundTop;
private boolean mAnimateNextBackgroundBottom;
private boolean mAnimateNextSectionBoundsChange;
private int mBgColor;
private float mDimAmount;
private ValueAnimator mDimAnimator;
- private ArrayList<ExpandableView> mTmpSortedChildren = new ArrayList<>();
+ private final ArrayList<ExpandableView> mTmpSortedChildren = new ArrayList<>();
private final Animator.AnimatorListener mDimEndListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mDimAnimator = null;
}
};
- private ValueAnimator.AnimatorUpdateListener mDimUpdateListener
+ private final ValueAnimator.AnimatorUpdateListener mDimUpdateListener
= new ValueAnimator.AnimatorUpdateListener() {
@Override
@@ -351,29 +344,23 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
};
protected ViewGroup mQsHeader;
// Rect of QsHeader. Kept as a field just to avoid creating a new one each time.
- private Rect mQsHeaderBound = new Rect();
+ private final Rect mQsHeaderBound = new Rect();
private boolean mContinuousShadowUpdate;
private boolean mContinuousBackgroundUpdate;
- private ViewTreeObserver.OnPreDrawListener mShadowUpdater
+ private final ViewTreeObserver.OnPreDrawListener mShadowUpdater
= () -> {
updateViewShadows();
return true;
};
- private ViewTreeObserver.OnPreDrawListener mBackgroundUpdater = () -> {
+ private final ViewTreeObserver.OnPreDrawListener mBackgroundUpdater = () -> {
updateBackground();
return true;
};
- private Comparator<ExpandableView> mViewPositionComparator = (view, otherView) -> {
+ private final Comparator<ExpandableView> mViewPositionComparator = (view, otherView) -> {
float endY = view.getTranslationY() + view.getActualHeight();
float otherEndY = otherView.getTranslationY() + otherView.getActualHeight();
- if (endY < otherEndY) {
- return -1;
- } else if (endY > otherEndY) {
- return 1;
- } else {
- // The two notifications end at the same location
- return 0;
- }
+ // Return zero when the two notifications end at the same location
+ return Float.compare(endY, otherEndY);
};
private final ViewOutlineProvider mOutlineProvider = new ViewOutlineProvider() {
@Override
@@ -435,16 +422,14 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private int mUpcomingStatusBarState;
private int mCachedBackgroundColor;
private boolean mHeadsUpGoingAwayAnimationsAllowed = true;
- private Runnable mReflingAndAnimateScroll = () -> {
- animateScroll();
- };
+ private final Runnable mReflingAndAnimateScroll = this::animateScroll;
private int mCornerRadius;
private int mMinimumPaddings;
private int mQsTilePadding;
private boolean mSkinnyNotifsInLandscape;
private int mSidePaddings;
private final Rect mBackgroundAnimationRect = new Rect();
- private ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>();
+ private final ArrayList<BiConsumer<Float, Float>> mExpandedHeightListeners = new ArrayList<>();
private int mHeadsUpInset;
/**
@@ -479,8 +464,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private int mWaterfallTopInset;
private NotificationStackScrollLayoutController mController;
- private boolean mKeyguardMediaControllorVisible;
-
/**
* The clip path used to clip the view in a rounded way.
*/
@@ -501,7 +484,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private int mRoundedRectClippingTop;
private int mRoundedRectClippingBottom;
private int mRoundedRectClippingRight;
- private float[] mBgCornerRadii = new float[8];
+ private final float[] mBgCornerRadii = new float[8];
/**
* Whether stackY should be animated in case the view is getting shorter than the scroll
@@ -527,7 +510,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
/**
* Corner radii of the launched notification if it's clipped
*/
- private float[] mLaunchedNotificationRadii = new float[8];
+ private final float[] mLaunchedNotificationRadii = new float[8];
/**
* The notification that is being launched currently.
@@ -779,7 +762,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
y = getLayoutHeight();
drawDebugInfo(canvas, y, Color.YELLOW, /* label= */ "getLayoutHeight() = " + y);
- y = (int) mMaxLayoutHeight;
+ y = mMaxLayoutHeight;
drawDebugInfo(canvas, y, Color.MAGENTA, /* label= */ "mMaxLayoutHeight = " + y);
// The space between mTopPadding and mKeyguardBottomPadding determines the available space
@@ -997,7 +980,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mOverflingDistance = configuration.getScaledOverflingDistance();
Resources res = context.getResources();
- mCollapsedSize = res.getDimensionPixelSize(R.dimen.notification_min_height);
mGapHeight = res.getDimensionPixelSize(R.dimen.notification_section_divider_height);
mStackScrollAlgorithm.initView(context);
mAmbientState.reload(context);
@@ -1256,12 +1238,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private void clampScrollPosition() {
int scrollRange = getScrollRange();
if (scrollRange < mOwnScrollY && !mAmbientState.isClearAllInProgress()) {
- boolean animateStackY = false;
- if (scrollRange < getScrollAmountToScrollBoundary()
- && mAnimateStackYForContentHeightChange) {
- // if the scroll boundary updates the position of the stack,
- animateStackY = true;
- }
+ // if the scroll boundary updates the position of the stack,
+ boolean animateStackY = scrollRange < getScrollAmountToScrollBoundary()
+ && mAnimateStackYForContentHeightChange;
setOwnScrollY(scrollRange, animateStackY);
}
}
@@ -1504,7 +1483,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
if (mAmbientState.isHiddenAtAll()) {
- clipToOutline = false;
invalidateOutline();
if (isFullyHidden()) {
setClipBounds(null);
@@ -1782,7 +1760,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
- private Runnable mReclamp = new Runnable() {
+ private final Runnable mReclamp = new Runnable() {
@Override
public void run() {
int range = getScrollRange();
@@ -3084,11 +3062,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
int currentIndex = indexOfChild(child);
if (currentIndex == -1) {
- boolean isTransient = false;
- if (child instanceof ExpandableNotificationRow
- && child.getTransientContainer() != null) {
- isTransient = true;
- }
+ boolean isTransient = child instanceof ExpandableNotificationRow
+ && child.getTransientContainer() != null;
Log.e(TAG, "Attempting to re-position "
+ (isTransient ? "transient" : "")
+ " view {"
@@ -3149,7 +3124,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private void generateHeadsUpAnimationEvents() {
for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
ExpandableNotificationRow row = eventPair.first;
- String key = row.getEntry().getKey();
boolean isHeadsUp = eventPair.second;
if (isHeadsUp != row.isHeadsUp()) {
// For cases where we have a heads up showing and appearing again we shouldn't
@@ -3212,10 +3186,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
private boolean shouldHunAppearFromBottom(ExpandableViewState viewState) {
- if (viewState.yTranslation + viewState.height < mAmbientState.getMaxHeadsUpTranslation()) {
- return false;
- }
- return true;
+ return viewState.yTranslation + viewState.height
+ >= mAmbientState.getMaxHeadsUpTranslation();
}
@ShadeViewRefactor(RefactorComponent.STATE_RESOLVER)
@@ -4790,7 +4762,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
public void setTrackingHeadsUp(ExpandableNotificationRow row) {
mAmbientState.setTrackedHeadsUpRow(row);
- mTrackingHeadsUp = row != null;
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
@@ -6176,7 +6147,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- private ExpandHelper.Callback mExpandHelperCallback = new ExpandHelper.Callback() {
+ private final ExpandHelper.Callback mExpandHelperCallback = new ExpandHelper.Callback() {
@Override
public ExpandableView getChildAtPosition(float touchX, float touchY) {
return NotificationStackScrollLayout.this.getChildAtPosition(touchX, touchY);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 5d5918de3d9e..d2c2d58820bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -14,6 +14,9 @@
package com.android.systemui.qs;
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
+import static com.android.systemui.statusbar.StatusBarState.SHADE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertTrue;
@@ -49,13 +52,13 @@ import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.media.MediaHost;
import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
import com.android.systemui.qs.external.TileServiceRequestController;
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
@@ -93,7 +96,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
@Mock private QSPanel.QSTileLayout mQsTileLayout;
@Mock private QSPanel.QSTileLayout mQQsTileLayout;
@Mock private QSAnimator mQSAnimator;
- @Mock private StatusBarStateController mStatusBarStateController;
+ @Mock private SysuiStatusBarStateController mStatusBarStateController;
@Mock private QSSquishinessController mSquishinessController;
private View mQsFragmentView;
@@ -158,7 +161,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
public void
transitionToFullShade_onKeyguard_noBouncer_setsAlphaUsingLinearInterpolator() {
QSFragment fragment = resumeAndGetFragment();
- setStatusBarState(StatusBarState.KEYGUARD);
+ setStatusBarState(KEYGUARD);
when(mQSPanelController.isBouncerInTransit()).thenReturn(false);
boolean isTransitioningToFullShade = true;
float transitionProgress = 0.5f;
@@ -174,7 +177,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
public void
transitionToFullShade_onKeyguard_bouncerActive_setsAlphaUsingBouncerInterpolator() {
QSFragment fragment = resumeAndGetFragment();
- setStatusBarState(StatusBarState.KEYGUARD);
+ setStatusBarState(KEYGUARD);
when(mQSPanelController.isBouncerInTransit()).thenReturn(true);
boolean isTransitioningToFullShade = true;
float transitionProgress = 0.5f;
@@ -262,6 +265,27 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
}
@Test
+ public void setQsExpansion_inSplitShade_whenTransitioningToKeyguard_setsAlphaBasedOnShadeTransitionProgress() {
+ QSFragment fragment = resumeAndGetFragment();
+ enableSplitShade();
+ when(mStatusBarStateController.getState()).thenReturn(SHADE);
+ when(mStatusBarStateController.getCurrentOrUpcomingState()).thenReturn(KEYGUARD);
+ boolean isTransitioningToFullShade = false;
+ float transitionProgress = 0;
+ float squishinessFraction = 0f;
+
+ fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress,
+ squishinessFraction);
+
+ // trigger alpha refresh with non-zero expansion and fraction values
+ fragment.setQsExpansion(/* expansion= */ 1, /* panelExpansionFraction= */1,
+ /* proposedTranslation= */ 0, /* squishinessFraction= */ 1);
+
+ // alpha should follow lockscreen to shade progress, not panel expansion fraction
+ assertThat(mQsFragmentView.getAlpha()).isEqualTo(transitionProgress);
+ }
+
+ @Test
public void getQsMinExpansionHeight_notInSplitShade_returnsHeaderHeight() {
QSFragment fragment = resumeAndGetFragment();
disableSplitShade();
@@ -402,6 +426,19 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
verify(mQSPanelController).setListening(eq(true), anyBoolean());
}
+ @Test
+ public void passCorrectExpansionState_inSplitShade() {
+ QSFragment fragment = resumeAndGetFragment();
+ enableSplitShade();
+ clearInvocations(mQSPanelController);
+
+ fragment.setExpanded(true);
+ verify(mQSPanelController).setExpanded(true);
+
+ fragment.setExpanded(false);
+ verify(mQSPanelController).setExpanded(false);
+ }
+
@Override
protected Fragment instantiate(Context context, String className, Bundle arguments) {
MockitoAnnotations.initMocks(this);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index b40d5ac69d7b..0c60d3c72c2a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -23,6 +23,9 @@ import static com.android.keyguard.KeyguardClockSwitch.SMALL;
import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
import static com.android.systemui.statusbar.StatusBarState.SHADE;
import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED;
+import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_CLOSED;
+import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_OPEN;
+import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_OPENING;
import static com.google.common.truth.Truth.assertThat;
@@ -1249,14 +1252,10 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
@Test
public void testQsToBeImmediatelyExpandedWhenOpeningPanelInSplitShade() {
enableSplitShade(/* enabled= */ true);
- // set panel state to CLOSED
- mPanelExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 0,
- /* expanded= */ false, /* tracking= */ false, /* dragDownPxAmount= */ 0);
+ mPanelExpansionStateManager.updateState(STATE_CLOSED);
assertThat(mNotificationPanelViewController.mQsExpandImmediate).isFalse();
- // change panel state to OPENING
- mPanelExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 0.5f,
- /* expanded= */ true, /* tracking= */ true, /* dragDownPxAmount= */ 100);
+ mPanelExpansionStateManager.updateState(STATE_OPENING);
assertThat(mNotificationPanelViewController.mQsExpandImmediate).isTrue();
}
@@ -1264,15 +1263,23 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
@Test
public void testQsNotToBeImmediatelyExpandedWhenGoingFromUnlockedToLocked() {
enableSplitShade(/* enabled= */ true);
- // set panel state to CLOSED
- mPanelExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 0,
- /* expanded= */ false, /* tracking= */ false, /* dragDownPxAmount= */ 0);
+ mPanelExpansionStateManager.updateState(STATE_CLOSED);
- // go to lockscreen, which also sets fraction to 1.0f and makes shade "expanded"
mStatusBarStateController.setState(KEYGUARD);
- mPanelExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 1,
- /* expanded= */ true, /* tracking= */ true, /* dragDownPxAmount= */ 0);
+ // going to lockscreen would trigger STATE_OPENING
+ mPanelExpansionStateManager.updateState(STATE_OPENING);
+
+ assertThat(mNotificationPanelViewController.mQsExpandImmediate).isFalse();
+ }
+
+ @Test
+ public void testQsImmediateResetsWhenPanelOpensOrCloses() {
+ mNotificationPanelViewController.mQsExpandImmediate = true;
+ mPanelExpansionStateManager.updateState(STATE_OPEN);
+ assertThat(mNotificationPanelViewController.mQsExpandImmediate).isFalse();
+ mNotificationPanelViewController.mQsExpandImmediate = true;
+ mPanelExpansionStateManager.updateState(STATE_CLOSED);
assertThat(mNotificationPanelViewController.mQsExpandImmediate).isFalse();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
index 2ee31265ff7b..2970807afb36 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinatorTest.kt
@@ -337,6 +337,40 @@ class HeadsUpCoordinatorTest : SysuiTestCase() {
}
@Test
+ fun testOnEntryUpdated_toAlert() {
+ // GIVEN that an entry is posted that should not heads up
+ setShouldHeadsUp(mEntry, false)
+ mCollectionListener.onEntryAdded(mEntry)
+
+ // WHEN it's updated to heads up
+ setShouldHeadsUp(mEntry)
+ mCollectionListener.onEntryUpdated(mEntry)
+ mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
+ mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
+
+ // THEN the notification alerts
+ finishBind(mEntry)
+ verify(mHeadsUpManager).showNotification(mEntry)
+ }
+
+ @Test
+ fun testOnEntryUpdated_toNotAlert() {
+ // GIVEN that an entry is posted that should heads up
+ setShouldHeadsUp(mEntry)
+ mCollectionListener.onEntryAdded(mEntry)
+
+ // WHEN it's updated to not heads up
+ setShouldHeadsUp(mEntry, false)
+ mCollectionListener.onEntryUpdated(mEntry)
+ mBeforeTransformGroupsListener.onBeforeTransformGroups(listOf(mEntry))
+ mBeforeFinalizeFilterListener.onBeforeFinalizeFilter(listOf(mEntry))
+
+ // THEN the notification is never bound or shown
+ verify(mHeadsUpViewBinder, never()).bindHeadsUpView(any(), any())
+ verify(mHeadsUpManager, never()).showNotification(any())
+ }
+
+ @Test
fun testOnEntryRemovedRemovesHeadsUpNotification() {
// GIVEN the current HUN is mEntry
addHUN(mEntry)
diff --git a/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
index dc9144a68e4c..0ab5a8afe907 100644
--- a/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
+++ b/services/companion/java/com/android/server/companion/AssociationRequestsProcessor.java
@@ -116,6 +116,7 @@ class AssociationRequestsProcessor {
private static final String EXTRA_APPLICATION_CALLBACK = "application_callback";
private static final String EXTRA_ASSOCIATION_REQUEST = "association_request";
private static final String EXTRA_RESULT_RECEIVER = "result_receiver";
+ private static final String EXTRA_FORCE_CANCEL_CONFIRMATION = "cancel_confirmation";
// AssociationRequestsProcessor -> UI
private static final int RESULT_CODE_ASSOCIATION_CREATED = 0;
@@ -195,21 +196,7 @@ class AssociationRequestsProcessor {
intent.putExtras(extras);
// 2b.3. Create a PendingIntent.
- final PendingIntent pendingIntent;
- final long token = Binder.clearCallingIdentity();
- try {
- // Using uid of the application that will own the association (usually the same
- // application that sent the request) allows us to have multiple "pending" association
- // requests at the same time.
- // If the application already has a pending association request, that PendingIntent
- // will be cancelled.
- pendingIntent = PendingIntent.getActivityAsUser(
- mContext, /*requestCode */ packageUid, intent,
- FLAG_ONE_SHOT | FLAG_CANCEL_CURRENT | FLAG_IMMUTABLE,
- /* options= */ null, UserHandle.CURRENT);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
+ final PendingIntent pendingIntent = createPendingIntent(packageUid, intent);
// 2b.4. Send the PendingIntent back to the app.
try {
@@ -217,6 +204,27 @@ class AssociationRequestsProcessor {
} catch (RemoteException ignore) { }
}
+ /**
+ * Process another AssociationRequest in CompanionDeviceActivity to cancel current dialog.
+ */
+ PendingIntent buildAssociationCancellationIntent(@NonNull String packageName,
+ @UserIdInt int userId) {
+ requireNonNull(packageName, "Package name MUST NOT be null");
+
+ enforceUsesCompanionDeviceFeature(mContext, userId, packageName);
+
+ final int packageUid = mPackageManager.getPackageUid(packageName, 0, userId);
+
+ final Bundle extras = new Bundle();
+ extras.putBoolean(EXTRA_FORCE_CANCEL_CONFIRMATION, true);
+
+ final Intent intent = new Intent();
+ intent.setComponent(ASSOCIATION_REQUEST_APPROVAL_ACTIVITY);
+ intent.putExtras(extras);
+
+ return createPendingIntent(packageUid, intent);
+ }
+
private void processAssociationRequestApproval(@NonNull AssociationRequest request,
@NonNull IAssociationRequestCallback callback,
@NonNull ResultReceiver resultReceiver, @Nullable MacAddress macAddress) {
@@ -286,6 +294,27 @@ class AssociationRequestsProcessor {
return !isRoleHolder;
}
+ private PendingIntent createPendingIntent(int packageUid, Intent intent) {
+ final PendingIntent pendingIntent;
+ final long token = Binder.clearCallingIdentity();
+
+ // Using uid of the application that will own the association (usually the same
+ // application that sent the request) allows us to have multiple "pending" association
+ // requests at the same time.
+ // If the application already has a pending association request, that PendingIntent
+ // will be cancelled except application wants to cancel the request by the system.
+ try {
+ pendingIntent = PendingIntent.getActivityAsUser(
+ mContext, /*requestCode */ packageUid, intent,
+ FLAG_ONE_SHOT | FLAG_CANCEL_CURRENT | FLAG_IMMUTABLE,
+ /* options= */ null, UserHandle.CURRENT);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
+ return pendingIntent;
+ }
+
private final ResultReceiver mOnRequestConfirmationReceiver =
new ResultReceiver(Handler.getMain()) {
@Override
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 85d314042496..56a5a8f829b7 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -549,6 +549,18 @@ public class CompanionDeviceManagerService extends SystemService {
}
@Override
+ public PendingIntent buildAssociationCancellationIntent(String packageName,
+ int userId) throws RemoteException {
+ Slog.i(TAG, "buildAssociationCancellationIntent() "
+ + "package=u" + userId + "/" + packageName);
+ enforceCallerCanManageAssociationsForPackage(getContext(), userId, packageName,
+ "build association cancellation intent");
+
+ return mAssociationRequestsProcessor.buildAssociationCancellationIntent(
+ packageName, userId);
+ }
+
+ @Override
public List<AssociationInfo> getAssociations(String packageName, int userId) {
enforceCallerCanManageAssociationsForPackage(getContext(), userId, packageName,
"get associations");
diff --git a/services/core/java/com/android/server/AlarmManagerInternal.java b/services/core/java/com/android/server/AlarmManagerInternal.java
index b2abdbd144b8..67aa2b9a89bb 100644
--- a/services/core/java/com/android/server/AlarmManagerInternal.java
+++ b/services/core/java/com/android/server/AlarmManagerInternal.java
@@ -16,8 +16,10 @@
package com.android.server;
+import android.annotation.CurrentTimeMillisLong;
import android.app.PendingIntent;
+import com.android.server.SystemClockTime.TimeConfidence;
import com.android.server.SystemTimeZone.TimeZoneConfidence;
public interface AlarmManagerInternal {
@@ -59,4 +61,15 @@ public interface AlarmManagerInternal {
* for details
*/
void setTimeZone(String tzId, @TimeZoneConfidence int confidence);
+
+ /**
+ * Sets the device's current time and time confidence.
+ *
+ * @param unixEpochTimeMillis the time
+ * @param confidence the confidence that {@code unixEpochTimeMillis} is correct, see {@link
+ * TimeConfidence} for details
+ * @param logMsg the reason the time is being changed, for bug report logging
+ */
+ void setTime(@CurrentTimeMillisLong long unixEpochTimeMillis, @TimeConfidence int confidence,
+ String logMsg);
}
diff --git a/services/core/java/com/android/server/SystemClockTime.java b/services/core/java/com/android/server/SystemClockTime.java
new file mode 100644
index 000000000000..46fbbb290ed2
--- /dev/null
+++ b/services/core/java/com/android/server/SystemClockTime.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server;
+
+import static java.lang.annotation.ElementType.TYPE_USE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Build;
+import android.os.Environment;
+import android.os.SystemProperties;
+import android.util.LocalLog;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * A set of static methods that encapsulate knowledge of how the system clock time and associated
+ * metadata are stored on Android.
+ */
+public final class SystemClockTime {
+
+ private static final String TAG = "SystemClockTime";
+
+ /**
+ * A log that records the decisions / decision metadata that affected the device's system clock
+ * time. This is logged in bug reports to assist with debugging issues with time.
+ */
+ @NonNull
+ private static final LocalLog sTimeDebugLog =
+ new LocalLog(30, false /* useLocalTimestamps */);
+
+
+ /**
+ * An annotation that indicates a "time confidence" value is expected.
+ *
+ * <p>The confidence indicates whether the time is expected to be correct. The confidence can be
+ * upgraded or downgraded over time. It can be used to decide whether a user could / should be
+ * asked to confirm the time. For example, during device set up low confidence would describe a
+ * time that has been initialized by default. The user may then be asked to confirm the time,
+ * moving it to a high confidence.
+ */
+ @Retention(SOURCE)
+ @Target(TYPE_USE)
+ @IntDef(prefix = "TIME_CONFIDENCE_",
+ value = { TIME_CONFIDENCE_LOW, TIME_CONFIDENCE_HIGH })
+ public @interface TimeConfidence {
+ }
+
+ /** Used when confidence is low and would (ideally) be confirmed by a user. */
+ public static final @TimeConfidence int TIME_CONFIDENCE_LOW = 0;
+
+ /**
+ * Used when confidence in the time is high and does not need to be confirmed by a user.
+ */
+ public static final @TimeConfidence int TIME_CONFIDENCE_HIGH = 100;
+
+ /**
+ * The confidence in the current time. Android's time confidence is held in memory because RTC
+ * hardware can forget / corrupt the time while the device is powered off. Therefore, on boot
+ * we can't assume the time is good, and so default it to "low" confidence until it is confirmed
+ * or explicitly set.
+ */
+ private static @TimeConfidence int sTimeConfidence = TIME_CONFIDENCE_LOW;
+
+ private static final long sNativeData = init();
+
+ private SystemClockTime() {
+ }
+
+ /**
+ * Sets the system clock time to a reasonable lower bound. Used during boot-up to ensure the
+ * device has a time that is better than a default like 1970-01-01.
+ */
+ public static void initializeIfRequired() {
+ // Use the most recent of Build.TIME, the root file system's timestamp, and the
+ // value of the ro.build.date.utc system property (which is in seconds).
+ final long systemBuildTime = Long.max(
+ 1000L * SystemProperties.getLong("ro.build.date.utc", -1L),
+ Long.max(Environment.getRootDirectory().lastModified(), Build.TIME));
+ long currentTimeMillis = getCurrentTimeMillis();
+ if (currentTimeMillis < systemBuildTime) {
+ String logMsg = "Current time only " + currentTimeMillis
+ + ", advancing to build time " + systemBuildTime;
+ Slog.i(TAG, logMsg);
+ setTimeAndConfidence(systemBuildTime, TIME_CONFIDENCE_LOW, logMsg);
+ }
+ }
+
+ /**
+ * Sets the system clock time and confidence. See also {@link #setConfidence(int, String)} for
+ * an alternative that only sets the confidence.
+ *
+ * @param unixEpochMillis the time to set
+ * @param confidence the confidence in {@code unixEpochMillis}. See {@link TimeConfidence} for
+ * details.
+ * @param logMsg a log message that can be included in bug reports that explains the update
+ */
+ public static void setTimeAndConfidence(
+ @CurrentTimeMillisLong long unixEpochMillis, int confidence, @NonNull String logMsg) {
+ synchronized (SystemClockTime.class) {
+ setTime(sNativeData, unixEpochMillis);
+ sTimeConfidence = confidence;
+ sTimeDebugLog.log(logMsg);
+ }
+ }
+
+ /**
+ * Sets the system clock confidence. See also {@link #setTimeAndConfidence(long, int, String)}
+ * for an alternative that sets the time and confidence.
+ *
+ * @param confidence the confidence in the system clock time. See {@link TimeConfidence} for
+ * details.
+ * @param logMsg a log message that can be included in bug reports that explains the update
+ */
+ public static void setConfidence(@TimeConfidence int confidence, @NonNull String logMsg) {
+ synchronized (SystemClockTime.class) {
+ sTimeConfidence = confidence;
+ sTimeDebugLog.log(logMsg);
+ }
+ }
+
+ /**
+ * Returns the system clock time. The same as {@link System#currentTimeMillis()}.
+ */
+ private static @CurrentTimeMillisLong long getCurrentTimeMillis() {
+ return System.currentTimeMillis();
+ }
+
+ /**
+ * Returns the system clock confidence. See {@link TimeConfidence} for details.
+ */
+ public static @TimeConfidence int getTimeConfidence() {
+ synchronized (SystemClockTime.class) {
+ return sTimeConfidence;
+ }
+ }
+
+ /**
+ * Adds an entry to the system time debug log that is included in bug reports. This method is
+ * intended to be used to record event that may lead to a time change, e.g. config or mode
+ * changes.
+ */
+ public static void addDebugLogEntry(@NonNull String logMsg) {
+ sTimeDebugLog.log(logMsg);
+ }
+
+ /**
+ * Dumps information about recent time / confidence changes to the supplied writer.
+ */
+ public static void dump(PrintWriter writer) {
+ sTimeDebugLog.dump(writer);
+ }
+
+ private static native long init();
+ private static native int setTime(long nativeData, @CurrentTimeMillisLong long millis);
+}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 481672e64d06..7cedf9c543f0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -247,6 +247,7 @@ import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionInfo;
import android.content.pm.PermissionMethod;
+import android.content.pm.PermissionName;
import android.content.pm.ProcessInfo;
import android.content.pm.ProviderInfo;
import android.content.pm.ProviderInfoList;
@@ -5987,8 +5988,9 @@ public class ActivityManagerService extends IActivityManager.Stub
* provided non-{@code null} {@code permission} before. Otherwise calls into
* {@link ActivityManager#checkComponentPermission(String, int, int, boolean)}.
*/
+ @PackageManager.PermissionResult
@PermissionMethod
- public static int checkComponentPermission(String permission, int pid, int uid,
+ public static int checkComponentPermission(@PermissionName String permission, int pid, int uid,
int owningUid, boolean exported) {
if (pid == MY_PID) {
return PackageManager.PERMISSION_GRANTED;
@@ -6034,8 +6036,9 @@ public class ActivityManagerService extends IActivityManager.Stub
* This can be called with or without the global lock held.
*/
@Override
+ @PackageManager.PermissionResult
@PermissionMethod
- public int checkPermission(String permission, int pid, int uid) {
+ public int checkPermission(@PermissionName String permission, int pid, int uid) {
if (permission == null) {
return PackageManager.PERMISSION_DENIED;
}
@@ -6046,8 +6049,9 @@ public class ActivityManagerService extends IActivityManager.Stub
* Binder IPC calls go through the public entry point.
* This can be called with or without the global lock held.
*/
+ @PackageManager.PermissionResult
@PermissionMethod
- int checkCallingPermission(String permission) {
+ int checkCallingPermission(@PermissionName String permission) {
return checkPermission(permission,
Binder.getCallingPid(),
Binder.getCallingUid());
@@ -6057,7 +6061,7 @@ public class ActivityManagerService extends IActivityManager.Stub
* This can be called with or without the global lock held.
*/
@PermissionMethod
- void enforceCallingPermission(String permission, String func) {
+ void enforceCallingPermission(@PermissionName String permission, String func) {
if (checkCallingPermission(permission)
== PackageManager.PERMISSION_GRANTED) {
return;
@@ -6074,7 +6078,6 @@ public class ActivityManagerService extends IActivityManager.Stub
/**
* This can be called with or without the global lock held.
*/
- @PermissionMethod
private void enforceCallingHasAtLeastOnePermission(String func, String... permissions) {
for (String permission : permissions) {
if (checkCallingPermission(permission) == PackageManager.PERMISSION_GRANTED) {
@@ -6093,7 +6096,8 @@ public class ActivityManagerService extends IActivityManager.Stub
/**
* This can be called with or without the global lock held.
*/
- void enforcePermission(String permission, int pid, int uid, String func) {
+ @PermissionMethod
+ void enforcePermission(@PermissionName String permission, int pid, int uid, String func) {
if (checkPermission(permission, pid, uid) == PackageManager.PERMISSION_GRANTED) {
return;
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index a41a311bd643..d9d29d650f03 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -831,6 +831,26 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
@Override
+ @EnforcePermission(BATTERY_STATS)
+ public long computeBatteryScreenOffRealtimeMs() {
+ synchronized (mStats) {
+ final long curTimeUs = SystemClock.elapsedRealtimeNanos() / 1000;
+ long timeUs = mStats.computeBatteryScreenOffRealtime(curTimeUs,
+ BatteryStats.STATS_SINCE_CHARGED);
+ return timeUs / 1000;
+ }
+ }
+
+ @Override
+ @EnforcePermission(BATTERY_STATS)
+ public long getScreenOffDischargeMah() {
+ synchronized (mStats) {
+ long dischargeUah = mStats.getUahDischargeScreenOff(BatteryStats.STATS_SINCE_CHARGED);
+ return dischargeUah / 1000;
+ }
+ }
+
+ @Override
@EnforcePermission(UPDATE_DEVICE_STATS)
public void noteEvent(final int code, final String name, final int uid) {
if (name == null) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthResult.java b/services/core/java/com/android/server/biometrics/sensors/AuthResult.java
new file mode 100644
index 000000000000..c0ebf6b8b634
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthResult.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import android.hardware.biometrics.BiometricManager;
+
+class AuthResult {
+ static final int FAILED = 0;
+ static final int LOCKED_OUT = 1;
+ static final int AUTHENTICATED = 2;
+ private final int mStatus;
+ private final int mBiometricStrength;
+
+ AuthResult(int status, @BiometricManager.Authenticators.Types int strength) {
+ mStatus = status;
+ mBiometricStrength = strength;
+ }
+
+ int getStatus() {
+ return mStatus;
+ }
+
+ int getBiometricStrength() {
+ return mBiometricStrength;
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthResultCoordinator.java b/services/core/java/com/android/server/biometrics/sensors/AuthResultCoordinator.java
new file mode 100644
index 000000000000..6d00c3fc15ea
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthResultCoordinator.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import android.hardware.biometrics.BiometricManager.Authenticators;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A class that takes in a series of authentication attempts (successes, failures, lockouts)
+ * across different biometric strengths (convenience, weak, strong) and returns a single AuthResult.
+ *
+ * The AuthResult will be the strongest biometric operation that occurred amongst all reported
+ * operations, and if multiple such operations exist, it will favor a successful authentication.
+ */
+class AuthResultCoordinator {
+
+ private static final String TAG = "AuthResultCoordinator";
+ private final List<AuthResult> mOperations;
+
+ AuthResultCoordinator() {
+ mOperations = new ArrayList<>();
+ }
+
+ /**
+ * Adds auth success for a given strength to the current operation list.
+ */
+ void authenticatedFor(@Authenticators.Types int strength) {
+ mOperations.add(new AuthResult(AuthResult.AUTHENTICATED, strength));
+ }
+
+ /**
+ * Adds auth ended for a given strength to the current operation list.
+ */
+ void authEndedFor(@Authenticators.Types int strength) {
+ mOperations.add(new AuthResult(AuthResult.FAILED, strength));
+ }
+
+ /**
+ * Adds a lock out of a given strength to the current operation list.
+ */
+ void lockedOutFor(@Authenticators.Types int strength) {
+ mOperations.add(new AuthResult(AuthResult.LOCKED_OUT, strength));
+ }
+
+ /**
+ * Obtains an auth result & strength from a current set of biometric operations.
+ */
+ AuthResult getResult() {
+ AuthResult result = new AuthResult(AuthResult.FAILED, Authenticators.BIOMETRIC_CONVENIENCE);
+ return mOperations.stream().filter(
+ (element) -> element.getStatus() != AuthResult.FAILED).reduce(result,
+ ((curr, next) -> {
+ int strengthCompare = curr.getBiometricStrength() - next.getBiometricStrength();
+ if (strengthCompare < 0) {
+ return curr;
+ } else if (strengthCompare == 0) {
+ // Equal level of strength, favor authentication.
+ if (curr.getStatus() == AuthResult.AUTHENTICATED) {
+ return curr;
+ } else {
+ // Either next is Authenticated, or it is not, either way return this
+ // one.
+ return next;
+ }
+ } else {
+ // curr is a weaker biometric
+ return next;
+ }
+ }));
+ }
+
+ void resetState() {
+ mOperations.clear();
+ }
+}
+
+
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java b/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java
new file mode 100644
index 000000000000..13840ff389d9
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthSessionCoordinator.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import android.hardware.biometrics.BiometricManager.Authenticators;
+import android.util.Slog;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Coordinates lockout counter enforcement for all types of biometric strengths across all users.
+ *
+ * This class is not thread-safe. In general, all calls to this class should be made on the same
+ * handler to ensure no collisions.
+ */
+class AuthSessionCoordinator implements AuthSessionListener {
+ private static final String TAG = "AuthSessionCoordinator";
+
+ private final Set<Integer> mAuthOperations;
+
+ private int mUserId;
+ private boolean mIsAuthenticating;
+ private AuthResultCoordinator mAuthResultCoordinator;
+ private MultiBiometricLockoutState mMultiBiometricLockoutState;
+
+ AuthSessionCoordinator() {
+ mAuthOperations = new HashSet<>();
+ mAuthResultCoordinator = new AuthResultCoordinator();
+ mMultiBiometricLockoutState = new MultiBiometricLockoutState();
+ }
+
+ /**
+ * A Call indicating that an auth session has started
+ */
+ void onAuthSessionStarted(int userId) {
+ mAuthOperations.clear();
+ mUserId = userId;
+ mIsAuthenticating = true;
+ mAuthResultCoordinator.resetState();
+ }
+
+ /**
+ * Ends the current auth session and updates the lockout state.
+ *
+ * This can happen two ways.
+ * 1. Manually calling this API
+ * 2. If authStartedFor() was called, and all authentication attempts finish.
+ */
+ void endAuthSession() {
+ if (mIsAuthenticating) {
+ mAuthOperations.clear();
+ AuthResult res =
+ mAuthResultCoordinator.getResult();
+ if (res.getStatus() == AuthResult.AUTHENTICATED) {
+ mMultiBiometricLockoutState.onUserUnlocked(mUserId, res.getBiometricStrength());
+ } else if (res.getStatus() == AuthResult.LOCKED_OUT) {
+ mMultiBiometricLockoutState.onUserLocked(mUserId, res.getBiometricStrength());
+ }
+ mAuthResultCoordinator.resetState();
+ mIsAuthenticating = false;
+ }
+ }
+
+ /**
+ * @return true if a user can authenticate with a given strength.
+ */
+ boolean getCanAuthFor(int userId, @Authenticators.Types int strength) {
+ return mMultiBiometricLockoutState.canUserAuthenticate(userId, strength);
+ }
+
+ @Override
+ public void authStartedFor(int userId, int sensorId) {
+ if (!mIsAuthenticating) {
+ onAuthSessionStarted(userId);
+ }
+
+ if (mAuthOperations.contains(sensorId)) {
+ Slog.e(TAG, "Error, authStartedFor(" + sensorId + ") without being finished");
+ return;
+ }
+
+ if (mUserId != userId) {
+ Slog.e(TAG, "Error authStartedFor(" + userId + ") Incorrect userId, expected" + mUserId
+ + ", ignoring...");
+ return;
+ }
+
+ mAuthOperations.add(sensorId);
+ }
+
+ @Override
+ public void authenticatedFor(int userId, @Authenticators.Types int biometricStrength,
+ int sensorId) {
+ mAuthResultCoordinator.authenticatedFor(biometricStrength);
+ attemptToFinish(userId, sensorId,
+ "authenticatedFor(userId=" + userId + ", biometricStrength=" + biometricStrength
+ + ", sensorId=" + sensorId + "");
+ }
+
+ @Override
+ public void lockedOutFor(int userId, @Authenticators.Types int biometricStrength,
+ int sensorId) {
+ mAuthResultCoordinator.lockedOutFor(biometricStrength);
+ attemptToFinish(userId, sensorId,
+ "lockOutFor(userId=" + userId + ", biometricStrength=" + biometricStrength
+ + ", sensorId=" + sensorId + "");
+ }
+
+ @Override
+ public void authEndedFor(int userId, @Authenticators.Types int biometricStrength,
+ int sensorId) {
+ mAuthResultCoordinator.authEndedFor(biometricStrength);
+ attemptToFinish(userId, sensorId,
+ "authEndedFor(userId=" + userId + " ,biometricStrength=" + biometricStrength
+ + ", sensorId=" + sensorId);
+ }
+
+ @Override
+ public void resetLockoutFor(int userId, @Authenticators.Types int biometricStrength) {
+ mMultiBiometricLockoutState.onUserUnlocked(userId, biometricStrength);
+ }
+
+ private void attemptToFinish(int userId, int sensorId, String description) {
+ boolean didFail = false;
+ if (!mAuthOperations.contains(sensorId)) {
+ Slog.e(TAG, "Error unable to find auth operation : " + description);
+ didFail = true;
+ }
+ if (userId != mUserId) {
+ Slog.e(TAG, "Error mismatched userId, expected=" + mUserId + " for " + description);
+ didFail = true;
+ }
+ if (didFail) {
+ return;
+ }
+ mAuthOperations.remove(sensorId);
+ if (mIsAuthenticating && mAuthOperations.isEmpty()) {
+ endAuthSession();
+ }
+ }
+
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthSessionListener.java b/services/core/java/com/android/server/biometrics/sensors/AuthSessionListener.java
new file mode 100644
index 000000000000..8b1f90af0234
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthSessionListener.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import android.hardware.biometrics.BiometricManager.Authenticators;
+
+/**
+ * An interface that listens to authentication events.
+ */
+interface AuthSessionListener {
+ /**
+ * Indicates an auth operation has started for a given user and sensor.
+ */
+ void authStartedFor(int userId, int sensorId);
+
+ /**
+ * Indicates a successful authentication occurred for a sensor of a given strength.
+ */
+ void authenticatedFor(int userId, @Authenticators.Types int biometricStrength, int sensorId);
+
+ /**
+ * Indicates authentication ended for a sensor of a given strength.
+ */
+ void authEndedFor(int userId, @Authenticators.Types int biometricStrength, int sensorId);
+
+ /**
+ * Indicates a lockout occurred for a sensor of a given strength.
+ */
+ void lockedOutFor(int userId, @Authenticators.Types int biometricStrength, int sensorId);
+
+ /**
+ * Indicates that a reset lockout has happened for a given strength.
+ */
+ void resetLockoutFor(int uerId, @Authenticators.Types int biometricStrength);
+}
diff --git a/services/core/java/com/android/server/biometrics/sensors/MultiBiometricLockoutState.java b/services/core/java/com/android/server/biometrics/sensors/MultiBiometricLockoutState.java
new file mode 100644
index 000000000000..49dc817c7fd5
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/sensors/MultiBiometricLockoutState.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import static android.hardware.biometrics.BiometricManager.Authenticators;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_STRONG;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_WEAK;
+
+import android.util.ArrayMap;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is used as a system to store the state of each
+ * {@link Authenticators.Types} status for every user.
+ */
+class MultiBiometricLockoutState {
+
+ private static final String TAG = "MultiBiometricLockoutState";
+ private static final Map<Integer, List<Integer>> PRECEDENCE;
+
+ static {
+ Map<Integer, List<Integer>> precedence = new ArrayMap<>();
+ precedence.put(Authenticators.BIOMETRIC_STRONG,
+ Arrays.asList(BIOMETRIC_STRONG, BIOMETRIC_WEAK, BIOMETRIC_CONVENIENCE));
+ precedence.put(BIOMETRIC_WEAK, Arrays.asList(BIOMETRIC_WEAK, BIOMETRIC_CONVENIENCE));
+ precedence.put(BIOMETRIC_CONVENIENCE, Arrays.asList(BIOMETRIC_CONVENIENCE));
+ PRECEDENCE = Collections.unmodifiableMap(precedence);
+ }
+
+ private final Map<Integer, Map<Integer, Boolean>> mCanUserAuthenticate;
+
+ @VisibleForTesting
+ MultiBiometricLockoutState() {
+ mCanUserAuthenticate = new HashMap<>();
+ }
+
+ private static Map<Integer, Boolean> createLockedOutMap() {
+ Map<Integer, Boolean> lockOutMap = new HashMap<>();
+ lockOutMap.put(BIOMETRIC_STRONG, false);
+ lockOutMap.put(BIOMETRIC_WEAK, false);
+ lockOutMap.put(BIOMETRIC_CONVENIENCE, false);
+ return lockOutMap;
+ }
+
+ private Map<Integer, Boolean> getAuthMapForUser(int userId) {
+ if (!mCanUserAuthenticate.containsKey(userId)) {
+ mCanUserAuthenticate.put(userId, createLockedOutMap());
+ }
+ return mCanUserAuthenticate.get(userId);
+ }
+
+ /**
+ * Indicates a {@link Authenticators} has been locked for userId.
+ *
+ * @param userId The user.
+ * @param strength The strength of biometric that is requested to be locked.
+ */
+ void onUserLocked(int userId, @Authenticators.Types int strength) {
+ Slog.d(TAG, "onUserLocked(userId=" + userId + ", strength=" + strength + ")");
+ Map<Integer, Boolean> canUserAuthState = getAuthMapForUser(userId);
+ for (int strengthToLockout : PRECEDENCE.get(strength)) {
+ canUserAuthState.put(strengthToLockout, false);
+ }
+ }
+
+ /**
+ * Indicates that a user has unlocked a {@link Authenticators}
+ *
+ * @param userId The user.
+ * @param strength The strength of biometric that is unlocked.
+ */
+ void onUserUnlocked(int userId, @Authenticators.Types int strength) {
+ Slog.d(TAG, "onUserUnlocked(userId=" + userId + ", strength=" + strength + ")");
+ Map<Integer, Boolean> canUserAuthState = getAuthMapForUser(userId);
+ for (int strengthToLockout : PRECEDENCE.get(strength)) {
+ canUserAuthState.put(strengthToLockout, true);
+ }
+ }
+
+ /**
+ * Indicates if a user can perform an authentication operation with a given
+ * {@link Authenticators.Types}
+ *
+ * @param userId The user.
+ * @param strength The strength of biometric that is requested to authenticate.
+ * @return If a user can authenticate with a given biometric of this strength.
+ */
+ boolean canUserAuthenticate(int userId, @Authenticators.Types int strength) {
+ final boolean canAuthenticate = getAuthMapForUser(userId).get(strength);
+ Slog.d(TAG, "canUserAuthenticate(userId=" + userId + ", strength=" + strength + ") ="
+ + canAuthenticate);
+ return canAuthenticate;
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
index 3e397468aa87..82436cc0890a 100644
--- a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
+++ b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
@@ -221,14 +221,12 @@ final class IInputMethodInvoker {
}
@AnyThread
- boolean updateEditorToolType(int toolType) {
+ void updateEditorToolType(@MotionEvent.ToolType int toolType) {
try {
mTarget.updateEditorToolType(toolType);
} catch (RemoteException e) {
logRemoteException(e);
- return false;
}
- return true;
}
@AnyThread
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 31e0693ed47c..2b74eeb4bfe8 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -69,7 +69,6 @@ import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppGlobals;
-import android.app.AppOpsManager;
import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
@@ -298,8 +297,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
final IWindowManager mIWindowManager;
private final SparseBooleanArray mLoggedDeniedGetInputMethodWindowVisibleHeightForUid =
new SparseBooleanArray(0);
- private final SparseBooleanArray mLoggedDeniedIsInputMethodPickerShownForTestForUid =
- new SparseBooleanArray(0);
final WindowManagerInternal mWindowManagerInternal;
final PackageManagerInternal mPackageManagerInternal;
final InputManagerInternal mInputManagerInternal;
@@ -309,7 +306,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
final boolean mHasFeature;
private final ArrayMap<String, List<InputMethodSubtype>> mAdditionalSubtypeMap =
new ArrayMap<>();
- private final AppOpsManager mAppOpsManager;
private final UserManager mUserManager;
private final UserManagerInternal mUserManagerInternal;
private final InputMethodMenuController mMenuController;
@@ -1479,7 +1475,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
public void onUidRemoved(int uid) {
synchronized (ImfLock.class) {
mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.delete(uid);
- mLoggedDeniedIsInputMethodPickerShownForTestForUid.delete(uid);
}
}
@@ -1737,7 +1732,6 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
mInputMethodDeviceConfigs = new InputMethodDeviceConfigs();
mImeDisplayValidator = mWindowManagerInternal::getDisplayImePolicy;
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
- mAppOpsManager = mContext.getSystemService(AppOpsManager.class);
mUserManager = mContext.getSystemService(UserManager.class);
mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
mAccessibilityManager = AccessibilityManager.getInstance(context);
@@ -2523,7 +2517,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
null, null, null, selectedMethodId, getSequenceNumberLocked(), null, false);
}
- if (!InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, cs.mUid,
+ if (!InputMethodUtils.checkIfPackageBelongsToUid(mPackageManagerInternal, cs.mUid,
editorInfo.packageName)) {
Slog.e(TAG, "Rejecting this client as it reported an invalid package name."
+ " uid=" + cs.mUid + " package=" + editorInfo.packageName);
@@ -2960,19 +2954,17 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
hideStatusBarIconLocked();
} else if (packageName != null) {
if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
- CharSequence contentDescription = null;
+ final PackageManager userAwarePackageManager =
+ getPackageManagerForUser(mContext, mSettings.getCurrentUserId());
+ ApplicationInfo applicationInfo = null;
try {
- // Use PackageManager to load label
- final PackageManager packageManager = mContext.getPackageManager();
- final ApplicationInfo applicationInfo = mIPackageManager
- .getApplicationInfo(packageName, 0, mSettings.getCurrentUserId());
- if (applicationInfo != null) {
- contentDescription = packageManager
- .getApplicationLabel(applicationInfo);
- }
- } catch (RemoteException e) {
- /* ignore */
+ applicationInfo = userAwarePackageManager.getApplicationInfo(packageName,
+ PackageManager.ApplicationInfoFlags.of(0));
+ } catch (PackageManager.NameNotFoundException e) {
}
+ final CharSequence contentDescription = applicationInfo != null
+ ? userAwarePackageManager.getApplicationLabel(applicationInfo)
+ : null;
if (mStatusBar != null) {
mStatusBar.setIcon(mSlotIme, packageName, iconId, 0,
contentDescription != null
@@ -3962,7 +3954,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
return false;
}
if (getCurIntentLocked() != null && InputMethodUtils.checkIfPackageBelongsToUid(
- mAppOpsManager,
+ mPackageManagerInternal,
uid,
getCurIntentLocked().getComponent().getPackageName())) {
return true;
@@ -4002,19 +3994,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
/**
* A test API for CTS to make sure that the input method menu is showing.
*/
+ @EnforcePermission(Manifest.permission.TEST_INPUT_METHOD)
public boolean isInputMethodPickerShownForTest() {
- if (mContext.checkCallingPermission(android.Manifest.permission.TEST_INPUT_METHOD)
- != PackageManager.PERMISSION_GRANTED) {
- final int callingUid = Binder.getCallingUid();
- synchronized (ImfLock.class) {
- if (!mLoggedDeniedIsInputMethodPickerShownForTestForUid.get(callingUid)) {
- EventLog.writeEvent(0x534e4554, "237317525", callingUid, "");
- mLoggedDeniedIsInputMethodPickerShownForTestForUid.put(callingUid, true);
- }
- }
- throw new SecurityException(
- "isInputMethodPickerShownForTest requires TEST_INPUT_METHOD permission");
- }
synchronized (ImfLock.class) {
return mMenuController.isisInputMethodPickerShownForTestLocked();
}
@@ -4224,8 +4205,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
final int callingUid = Binder.getCallingUid();
final ComponentName imeComponentName =
imeId != null ? ComponentName.unflattenFromString(imeId) : null;
- if (imeComponentName == null || !InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager,
- callingUid, imeComponentName.getPackageName())) {
+ if (imeComponentName == null || !InputMethodUtils.checkIfPackageBelongsToUid(
+ mPackageManagerInternal, callingUid, imeComponentName.getPackageName())) {
throw new SecurityException("Calling UID=" + callingUid + " does not belong to imeId="
+ imeId);
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index beeaa90a3832..054c994dddc5 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -20,12 +20,12 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserHandleAware;
import android.annotation.UserIdInt;
-import android.app.AppOpsManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
import android.content.res.Resources;
import android.os.Binder;
import android.os.Build;
@@ -80,29 +80,6 @@ final class InputMethodUtils {
}
// ----------------------------------------------------------------------
- // Utilities for debug
- static String getApiCallStack() {
- String apiCallStack = "";
- try {
- throw new RuntimeException();
- } catch (RuntimeException e) {
- final StackTraceElement[] frames = e.getStackTrace();
- for (int j = 1; j < frames.length; ++j) {
- final String tempCallStack = frames[j].toString();
- if (TextUtils.isEmpty(apiCallStack)) {
- // Overwrite apiCallStack if it's empty
- apiCallStack = tempCallStack;
- } else if (tempCallStack.indexOf("Transact(") < 0) {
- // Overwrite apiCallStack if it's not a binder call
- apiCallStack = tempCallStack;
- } else {
- break;
- }
- }
- }
- return apiCallStack;
- }
- // ----------------------------------------------------------------------
static boolean canAddToLastInputMethod(InputMethodSubtype subtype) {
if (subtype == null) return true;
@@ -218,20 +195,20 @@ final class InputMethodUtils {
/**
* Returns true if a package name belongs to a UID.
*
- * <p>This is a simple wrapper of {@link AppOpsManager#checkPackage(int, String)}.</p>
- * @param appOpsManager the {@link AppOpsManager} object to be used for the validation.
+ * <p>This is a simple wrapper of
+ * {@link PackageManagerInternal#getPackageUid(String, long, int)}.</p>
+ * @param packageManagerInternal the {@link PackageManagerInternal} object to be used for the
+ * validation.
* @param uid the UID to be validated.
* @param packageName the package name.
* @return {@code true} if the package name belongs to the UID.
*/
- static boolean checkIfPackageBelongsToUid(AppOpsManager appOpsManager,
- @UserIdInt int uid, String packageName) {
- try {
- appOpsManager.checkPackage(uid, packageName);
- return true;
- } catch (SecurityException e) {
- return false;
- }
+ static boolean checkIfPackageBelongsToUid(PackageManagerInternal packageManagerInternal,
+ int uid, String packageName) {
+ // PackageManagerInternal#getPackageUid() doesn't check MATCH_INSTANT/MATCH_APEX as of
+ // writing. So setting 0 should be fine.
+ return packageManagerInternal.getPackageUid(packageName, 0 /* flags */,
+ UserHandle.getUserId(uid)) == uid;
}
/**
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 62e145a66d0c..1dd796504ea3 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -58,6 +58,8 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.function.pooled.PooledLambda;
+import com.android.server.LocalServices;
+import com.android.server.pm.UserManagerInternal;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -87,6 +89,7 @@ class MediaRouter2ServiceImpl {
private static final int PACKAGE_IMPORTANCE_FOR_DISCOVERY = IMPORTANCE_FOREGROUND_SERVICE;
private final Context mContext;
+ private final UserManagerInternal mUserManagerInternal;
private final Object mLock = new Object();
final AtomicInteger mNextRouterOrManagerId = new AtomicInteger(1);
final ActivityManager mActivityManager;
@@ -99,7 +102,7 @@ class MediaRouter2ServiceImpl {
@GuardedBy("mLock")
private final ArrayMap<IBinder, ManagerRecord> mAllManagerRecords = new ArrayMap<>();
@GuardedBy("mLock")
- private int mCurrentUserId = -1;
+ private int mCurrentActiveUserId = -1;
private final ActivityManager.OnUidImportanceListener mOnUidImportanceListener =
(uid, importance) -> {
@@ -125,12 +128,13 @@ class MediaRouter2ServiceImpl {
}
};
- MediaRouter2ServiceImpl(Context context) {
+ /* package */ MediaRouter2ServiceImpl(Context context) {
mContext = context;
mActivityManager = mContext.getSystemService(ActivityManager.class);
mActivityManager.addOnUidImportanceListener(mOnUidImportanceListener,
PACKAGE_IMPORTANCE_FOR_DISCOVERY);
mPowerManager = mContext.getSystemService(PowerManager.class);
+ mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
IntentFilter screenOnOffIntentFilter = new IntentFilter();
screenOnOffIntentFilter.addAction(ACTION_SCREEN_ON);
@@ -608,7 +612,7 @@ class MediaRouter2ServiceImpl {
synchronized (mLock) {
pw.println(indent + "mNextRouterOrManagerId=" + mNextRouterOrManagerId.get());
- pw.println(indent + "mCurrentUserId=" + mCurrentUserId);
+ pw.println(indent + "mCurrentActiveUserId=" + mCurrentActiveUserId);
pw.println(indent + "UserRecords:");
if (mUserRecords.size() > 0) {
@@ -621,24 +625,23 @@ class MediaRouter2ServiceImpl {
}
}
- // TODO(b/136703681): Review this is handling multi-user properly.
- void switchUser(int userId) {
+ /* package */ void updateRunningUserAndProfiles(int newActiveUserId) {
synchronized (mLock) {
- if (mCurrentUserId != userId) {
- final int oldUserId = mCurrentUserId;
- mCurrentUserId = userId; // do this first
-
- UserRecord oldUser = mUserRecords.get(oldUserId);
- if (oldUser != null) {
- oldUser.mHandler.sendMessage(
- obtainMessage(UserHandler::stop, oldUser.mHandler));
- disposeUserIfNeededLocked(oldUser); // since no longer current user
- }
-
- UserRecord newUser = mUserRecords.get(userId);
- if (newUser != null) {
- newUser.mHandler.sendMessage(
- obtainMessage(UserHandler::start, newUser.mHandler));
+ if (mCurrentActiveUserId != newActiveUserId) {
+ mCurrentActiveUserId = newActiveUserId;
+ for (int i = 0; i < mUserRecords.size(); i++) {
+ int userId = mUserRecords.keyAt(i);
+ UserRecord userRecord = mUserRecords.valueAt(i);
+ if (isUserActiveLocked(userId)) {
+ // userId corresponds to the active user, or one of its profiles. We
+ // ensure the associated structures are initialized.
+ userRecord.mHandler.sendMessage(
+ obtainMessage(UserHandler::start, userRecord.mHandler));
+ } else {
+ userRecord.mHandler.sendMessage(
+ obtainMessage(UserHandler::stop, userRecord.mHandler));
+ disposeUserIfNeededLocked(userRecord);
+ }
}
}
}
@@ -656,11 +659,21 @@ class MediaRouter2ServiceImpl {
}
}
+ /**
+ * Returns {@code true} if the given {@code userId} corresponds to the active user or a profile
+ * of the active user, returns {@code false} otherwise.
+ */
+ @GuardedBy("mLock")
+ private boolean isUserActiveLocked(int userId) {
+ return mUserManagerInternal.getProfileParentId(userId) == mCurrentActiveUserId;
+ }
+
////////////////////////////////////////////////////////////////
//// ***Locked methods related to MediaRouter2
//// - Should have @NonNull/@Nullable on all arguments
////////////////////////////////////////////////////////////////
+ @GuardedBy("mLock")
private void registerRouter2Locked(@NonNull IMediaRouter2 router, int uid, int pid,
@NonNull String packageName, int userId, boolean hasConfigureWifiDisplayPermission,
boolean hasModifyAudioRoutingPermission) {
@@ -688,6 +701,7 @@ class MediaRouter2ServiceImpl {
userRecord.mHandler, routerRecord));
}
+ @GuardedBy("mLock")
private void unregisterRouter2Locked(@NonNull IMediaRouter2 router, boolean died) {
RouterRecord routerRecord = mAllRouterRecords.remove(router.asBinder());
if (routerRecord == null) {
@@ -910,6 +924,7 @@ class MediaRouter2ServiceImpl {
return sessionInfos;
}
+ @GuardedBy("mLock")
private void registerManagerLocked(@NonNull IMediaRouter2Manager manager,
int uid, int pid, @NonNull String packageName, int userId) {
final IBinder binder = manager.asBinder();
@@ -1145,13 +1160,14 @@ class MediaRouter2ServiceImpl {
//// - Should have @NonNull/@Nullable on all arguments
////////////////////////////////////////////////////////////
+ @GuardedBy("mLock")
private UserRecord getOrCreateUserRecordLocked(int userId) {
UserRecord userRecord = mUserRecords.get(userId);
if (userRecord == null) {
userRecord = new UserRecord(userId);
mUserRecords.put(userId, userRecord);
userRecord.init();
- if (userId == mCurrentUserId) {
+ if (isUserActiveLocked(userId)) {
userRecord.mHandler.sendMessage(
obtainMessage(UserHandler::start, userRecord.mHandler));
}
@@ -1159,12 +1175,13 @@ class MediaRouter2ServiceImpl {
return userRecord;
}
+ @GuardedBy("mLock")
private void disposeUserIfNeededLocked(@NonNull UserRecord userRecord) {
// If there are no records left and the user is no longer current then go ahead
// and purge the user record and all of its associated state. If the user is current
// then leave it alone since we might be connected to a route or want to query
// the same route information again soon.
- if (userRecord.mUserId != mCurrentUserId
+ if (!isUserActiveLocked(userRecord.mUserId)
&& userRecord.mRouterRecords.isEmpty()
&& userRecord.mManagerRecords.isEmpty()) {
if (DEBUG) {
@@ -2438,6 +2455,7 @@ class MediaRouter2ServiceImpl {
pw.println(indent + "mUniqueRequestId=" + mUniqueRequestId);
pw.println(indent + "mManagerRequestId=" + mManagerRequestId);
mOldSession.dump(pw, indent);
+ mRoute.dump(pw, prefix);
}
}
}
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index d7d0b42aa0a7..511026e71d23 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -63,7 +63,9 @@ import android.util.SparseArray;
import android.util.TimeUtils;
import com.android.internal.util.DumpUtils;
+import com.android.server.LocalServices;
import com.android.server.Watchdog;
+import com.android.server.pm.UserManagerInternal;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -104,9 +106,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// State guarded by mLock.
private final Object mLock = new Object();
+ private final UserManagerInternal mUserManagerInternal;
private final SparseArray<UserRecord> mUserRecords = new SparseArray<>();
private final ArrayMap<IBinder, ClientRecord> mAllClientRecords = new ArrayMap<>();
- private int mCurrentUserId = -1;
+ private int mCurrentActiveUserId = -1;
private final IAudioService mAudioService;
private final AudioPlayerStateMonitor mAudioPlayerStateMonitor;
private final Handler mHandler = new Handler();
@@ -132,6 +135,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
mBluetoothA2dpRouteId =
res.getString(com.android.internal.R.string.bluetooth_a2dp_audio_route_id);
+ mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
mAudioService = IAudioService.Stub.asInterface(
ServiceManager.getService(Context.AUDIO_SERVICE));
mAudioPlayerStateMonitor = AudioPlayerStateMonitor.getInstance(context);
@@ -164,11 +168,11 @@ public final class MediaRouterService extends IMediaRouterService.Stub
new UserSwitchObserver() {
@Override
public void onUserSwitchComplete(int newUserId) {
- switchUser(newUserId);
+ updateRunningUserAndProfiles(newUserId);
}
},
TAG);
- switchUser(ActivityManager.getCurrentUser());
+ updateRunningUserAndProfiles(ActivityManager.getCurrentUser());
}
@Override
@@ -388,7 +392,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
pw.println("MEDIA ROUTER SERVICE (dumpsys media_router)");
pw.println();
pw.println("Global state");
- pw.println(" mCurrentUserId=" + mCurrentUserId);
+ pw.println(" mCurrentUserId=" + mCurrentActiveUserId);
synchronized (mLock) {
final int count = mUserRecords.size();
@@ -645,25 +649,31 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
- void switchUser(int userId) {
+ /**
+ * Starts all {@link UserRecord user records} associated with the active user (whose ID is
+ * {@code newActiveUserId}) or the active user's profiles.
+ *
+ * <p>All other records are stopped, and those without associated client records are removed.
+ */
+ private void updateRunningUserAndProfiles(int newActiveUserId) {
synchronized (mLock) {
- if (mCurrentUserId != userId) {
- final int oldUserId = mCurrentUserId;
- mCurrentUserId = userId; // do this first
-
- UserRecord oldUser = mUserRecords.get(oldUserId);
- if (oldUser != null) {
- oldUser.mHandler.sendEmptyMessage(UserHandler.MSG_STOP);
- disposeUserIfNeededLocked(oldUser); // since no longer current user
- }
-
- UserRecord newUser = mUserRecords.get(userId);
- if (newUser != null) {
- newUser.mHandler.sendEmptyMessage(UserHandler.MSG_START);
+ if (mCurrentActiveUserId != newActiveUserId) {
+ mCurrentActiveUserId = newActiveUserId;
+ for (int i = 0; i < mUserRecords.size(); i++) {
+ int userId = mUserRecords.keyAt(i);
+ UserRecord userRecord = mUserRecords.valueAt(i);
+ if (isUserActiveLocked(userId)) {
+ // userId corresponds to the active user, or one of its profiles. We
+ // ensure the associated structures are initialized.
+ userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START);
+ } else {
+ userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_STOP);
+ disposeUserIfNeededLocked(userRecord);
+ }
}
}
}
- mService2.switchUser(userId);
+ mService2.updateRunningUserAndProfiles(newActiveUserId);
}
void clientDied(ClientRecord clientRecord) {
@@ -718,8 +728,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
clientRecord.mGroupId = groupId;
if (groupId != null) {
userRecord.addToGroup(groupId, clientRecord);
- userRecord.mHandler.obtainMessage(UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, groupId)
- .sendToTarget();
+ userRecord
+ .mHandler
+ .obtainMessage(UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, groupId)
+ .sendToTarget();
}
}
@@ -805,9 +817,13 @@ public final class MediaRouterService extends IMediaRouterService.Stub
clientRecord.mUserRecord.mClientGroupMap.get(clientRecord.mGroupId);
if (group != null) {
group.mSelectedRouteId = routeId;
- clientRecord.mUserRecord.mHandler.obtainMessage(
- UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED, clientRecord.mGroupId)
- .sendToTarget();
+ clientRecord
+ .mUserRecord
+ .mHandler
+ .obtainMessage(
+ UserHandler.MSG_NOTIFY_GROUP_ROUTE_SELECTED,
+ clientRecord.mGroupId)
+ .sendToTarget();
}
}
}
@@ -839,7 +855,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
if (DEBUG) {
Slog.d(TAG, userRecord + ": Initialized");
}
- if (userRecord.mUserId == mCurrentUserId) {
+ if (isUserActiveLocked(userRecord.mUserId)) {
userRecord.mHandler.sendEmptyMessage(UserHandler.MSG_START);
}
}
@@ -849,8 +865,7 @@ public final class MediaRouterService extends IMediaRouterService.Stub
// and purge the user record and all of its associated state. If the user is current
// then leave it alone since we might be connected to a route or want to query
// the same route information again soon.
- if (userRecord.mUserId != mCurrentUserId
- && userRecord.mClientRecords.isEmpty()) {
+ if (!isUserActiveLocked(userRecord.mUserId) && userRecord.mClientRecords.isEmpty()) {
if (DEBUG) {
Slog.d(TAG, userRecord + ": Disposed");
}
@@ -859,6 +874,14 @@ public final class MediaRouterService extends IMediaRouterService.Stub
}
}
+ /**
+ * Returns {@code true} if the given {@code userId} corresponds to the active user or a profile
+ * of the active user, returns {@code false} otherwise.
+ */
+ private boolean isUserActiveLocked(int userId) {
+ return mUserManagerInternal.getProfileParentId(userId) == mCurrentActiveUserId;
+ }
+
private void initializeClientLocked(ClientRecord clientRecord) {
if (DEBUG) {
Slog.d(TAG, clientRecord + ": Registered");
@@ -898,7 +921,10 @@ public final class MediaRouterService extends IMediaRouterService.Stub
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED)) {
- BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE, android.bluetooth.BluetoothDevice.class);
+ BluetoothDevice btDevice =
+ intent.getParcelableExtra(
+ BluetoothDevice.EXTRA_DEVICE,
+ android.bluetooth.BluetoothDevice.class);
synchronized (mLock) {
mActiveBluetoothDevice = btDevice;
mGlobalBluetoothA2dpOn = btDevice != null;
diff --git a/services/core/java/com/android/server/om/IdmapDaemon.java b/services/core/java/com/android/server/om/IdmapDaemon.java
index bea616869014..56390a9f6b0e 100644
--- a/services/core/java/com/android/server/om/IdmapDaemon.java
+++ b/services/core/java/com/android/server/om/IdmapDaemon.java
@@ -217,6 +217,7 @@ class IdmapDaemon {
synchronized List<FabricatedOverlayInfo> getFabricatedOverlayInfos() {
final ArrayList<FabricatedOverlayInfo> allInfos = new ArrayList<>();
Connection c = null;
+ int iteratorId = -1;
try {
c = connect();
final IIdmap2 service = c.getIdmap2();
@@ -225,9 +226,9 @@ class IdmapDaemon {
return Collections.emptyList();
}
- service.acquireFabricatedOverlayIterator();
+ iteratorId = service.acquireFabricatedOverlayIterator();
List<FabricatedOverlayInfo> infos;
- while (!(infos = service.nextFabricatedOverlayInfos()).isEmpty()) {
+ while (!(infos = service.nextFabricatedOverlayInfos(iteratorId)).isEmpty()) {
allInfos.addAll(infos);
}
return allInfos;
@@ -235,8 +236,8 @@ class IdmapDaemon {
Slog.wtf(TAG, "failed to get all fabricated overlays", e);
} finally {
try {
- if (c.getIdmap2() != null) {
- c.getIdmap2().releaseFabricatedOverlayIterator();
+ if (c.getIdmap2() != null && iteratorId != -1) {
+ c.getIdmap2().releaseFabricatedOverlayIterator(iteratorId);
}
} catch (RemoteException e) {
// ignore
diff --git a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
index 372bcc6b07ca..46f335ef9fa2 100644
--- a/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
+++ b/services/core/java/com/android/server/timedetector/ConfigurationInternal.java
@@ -46,6 +46,7 @@ public final class ConfigurationInternal {
private final boolean mAutoDetectionSupported;
private final int mSystemClockUpdateThresholdMillis;
+ private final int mSystemClockConfidenceUpgradeThresholdMillis;
private final Instant mAutoSuggestionLowerBound;
private final Instant mManualSuggestionLowerBound;
private final Instant mSuggestionUpperBound;
@@ -57,6 +58,8 @@ public final class ConfigurationInternal {
private ConfigurationInternal(Builder builder) {
mAutoDetectionSupported = builder.mAutoDetectionSupported;
mSystemClockUpdateThresholdMillis = builder.mSystemClockUpdateThresholdMillis;
+ mSystemClockConfidenceUpgradeThresholdMillis =
+ builder.mSystemClockConfidenceUpgradeThresholdMillis;
mAutoSuggestionLowerBound = Objects.requireNonNull(builder.mAutoSuggestionLowerBound);
mManualSuggestionLowerBound = Objects.requireNonNull(builder.mManualSuggestionLowerBound);
mSuggestionUpperBound = Objects.requireNonNull(builder.mSuggestionUpperBound);
@@ -82,6 +85,17 @@ public final class ConfigurationInternal {
}
/**
+ * Return the absolute threshold at/below which the system clock confidence can be upgraded.
+ * i.e. if the detector receives a high-confidence time and the current system clock is +/- this
+ * value from that time and the confidence in the time is low, then the device's confidence in
+ * the current system clock time can be upgraded. This needs to be an amount users would
+ * consider "close enough".
+ */
+ public int getSystemClockConfidenceUpgradeThresholdMillis() {
+ return mSystemClockConfidenceUpgradeThresholdMillis;
+ }
+
+ /**
* Returns the lower bound for valid automatic time suggestions. It is guaranteed to be in the
* past, i.e. it is unrelated to the current system clock time.
* It holds no other meaning; it could be related to when the device system image was built,
@@ -242,6 +256,8 @@ public final class ConfigurationInternal {
return "ConfigurationInternal{"
+ "mAutoDetectionSupported=" + mAutoDetectionSupported
+ ", mSystemClockUpdateThresholdMillis=" + mSystemClockUpdateThresholdMillis
+ + ", mSystemClockConfidenceUpgradeThresholdMillis="
+ + mSystemClockConfidenceUpgradeThresholdMillis
+ ", mAutoSuggestionLowerBound=" + mAutoSuggestionLowerBound
+ "(" + mAutoSuggestionLowerBound.toEpochMilli() + ")"
+ ", mManualSuggestionLowerBound=" + mManualSuggestionLowerBound
@@ -258,6 +274,7 @@ public final class ConfigurationInternal {
static final class Builder {
private boolean mAutoDetectionSupported;
private int mSystemClockUpdateThresholdMillis;
+ private int mSystemClockConfidenceUpgradeThresholdMillis;
@NonNull private Instant mAutoSuggestionLowerBound;
@NonNull private Instant mManualSuggestionLowerBound;
@NonNull private Instant mSuggestionUpperBound;
@@ -286,68 +303,55 @@ public final class ConfigurationInternal {
this.mAutoDetectionEnabledSetting = toCopy.mAutoDetectionEnabledSetting;
}
- /**
- * Sets whether the user is allowed to configure time settings on this device.
- */
+ /** See {@link ConfigurationInternal#isUserConfigAllowed()}. */
Builder setUserConfigAllowed(boolean userConfigAllowed) {
mUserConfigAllowed = userConfigAllowed;
return this;
}
- /**
- * Sets whether automatic time detection is supported on this device.
- */
+ /** See {@link ConfigurationInternal#isAutoDetectionSupported()}. */
public Builder setAutoDetectionSupported(boolean supported) {
mAutoDetectionSupported = supported;
return this;
}
- /**
- * Sets the absolute threshold below which the system clock need not be updated. i.e. if
- * setting the system clock would adjust it by less than this (either backwards or forwards)
- * then it need not be set.
- */
+ /** See {@link ConfigurationInternal#getSystemClockUpdateThresholdMillis()}. */
public Builder setSystemClockUpdateThresholdMillis(int systemClockUpdateThresholdMillis) {
mSystemClockUpdateThresholdMillis = systemClockUpdateThresholdMillis;
return this;
}
- /**
- * Sets the lower bound for valid automatic time suggestions.
- */
+ /** See {@link ConfigurationInternal#getSystemClockConfidenceUpgradeThresholdMillis()}. */
+ public Builder setSystemClockConfidenceUpgradeThresholdMillis(int thresholdMillis) {
+ mSystemClockConfidenceUpgradeThresholdMillis = thresholdMillis;
+ return this;
+ }
+
+ /** See {@link ConfigurationInternal#getAutoSuggestionLowerBound()}. */
public Builder setAutoSuggestionLowerBound(@NonNull Instant autoSuggestionLowerBound) {
mAutoSuggestionLowerBound = Objects.requireNonNull(autoSuggestionLowerBound);
return this;
}
- /**
- * Sets the lower bound for valid manual time suggestions.
- */
+ /** See {@link ConfigurationInternal#getManualSuggestionLowerBound()}. */
public Builder setManualSuggestionLowerBound(@NonNull Instant manualSuggestionLowerBound) {
mManualSuggestionLowerBound = Objects.requireNonNull(manualSuggestionLowerBound);
return this;
}
- /**
- * Sets the upper bound for valid time suggestions (manual and automatic).
- */
+ /** See {@link ConfigurationInternal#getSuggestionUpperBound()}. */
public Builder setSuggestionUpperBound(@NonNull Instant suggestionUpperBound) {
mSuggestionUpperBound = Objects.requireNonNull(suggestionUpperBound);
return this;
}
- /**
- * Sets the order to look at time suggestions when automatically detecting time.
- * See {@code #ORIGIN_} constants
- */
+ /** See {@link ConfigurationInternal#getAutoOriginPriorities()}. */
public Builder setOriginPriorities(@NonNull @Origin int... originPriorities) {
mOriginPriorities = Objects.requireNonNull(originPriorities);
return this;
}
- /**
- * Sets the value of the automatic time detection enabled setting for this device.
- */
+ /** See {@link ConfigurationInternal#getAutoDetectionEnabledSetting()}. */
Builder setAutoDetectionEnabledSetting(boolean autoDetectionEnabledSetting) {
mAutoDetectionEnabledSetting = autoDetectionEnabledSetting;
return this;
diff --git a/services/core/java/com/android/server/timedetector/EnvironmentImpl.java b/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
index 3e02b463284d..4972412472f1 100644
--- a/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
+++ b/services/core/java/com/android/server/timedetector/EnvironmentImpl.java
@@ -16,16 +16,21 @@
package com.android.server.timedetector;
+import android.annotation.CurrentTimeMillisLong;
import android.annotation.NonNull;
-import android.app.AlarmManager;
import android.content.Context;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.Slog;
+import com.android.server.AlarmManagerInternal;
+import com.android.server.LocalServices;
+import com.android.server.SystemClockTime;
+import com.android.server.SystemClockTime.TimeConfidence;
import com.android.server.timezonedetector.ConfigurationChangeListener;
+import java.io.PrintWriter;
import java.util.Objects;
/**
@@ -38,7 +43,7 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
@NonNull private final Handler mHandler;
@NonNull private final ServiceConfigAccessor mServiceConfigAccessor;
@NonNull private final PowerManager.WakeLock mWakeLock;
- @NonNull private final AlarmManager mAlarmManager;
+ @NonNull private final AlarmManagerInternal mAlarmManagerInternal;
EnvironmentImpl(@NonNull Context context, @NonNull Handler handler,
@NonNull ServiceConfigAccessor serviceConfigAccessor) {
@@ -49,7 +54,8 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
mWakeLock = Objects.requireNonNull(
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG));
- mAlarmManager = Objects.requireNonNull(context.getSystemService(AlarmManager.class));
+ mAlarmManagerInternal = Objects.requireNonNull(
+ LocalServices.getService(AlarmManagerInternal.class));
}
@Override
@@ -84,9 +90,22 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
}
@Override
- public void setSystemClock(long newTimeMillis) {
+ public @TimeConfidence int systemClockConfidence() {
+ return SystemClockTime.getTimeConfidence();
+ }
+
+ @Override
+ public void setSystemClock(
+ @CurrentTimeMillisLong long newTimeMillis, @TimeConfidence int confidence,
+ @NonNull String logMsg) {
+ checkWakeLockHeld();
+ mAlarmManagerInternal.setTime(newTimeMillis, confidence, logMsg);
+ }
+
+ @Override
+ public void setSystemClockConfidence(@TimeConfidence int confidence, @NonNull String logMsg) {
checkWakeLockHeld();
- mAlarmManager.setTime(newTimeMillis);
+ SystemClockTime.setConfidence(confidence, logMsg);
}
@Override
@@ -100,4 +119,13 @@ final class EnvironmentImpl implements TimeDetectorStrategyImpl.Environment {
Slog.wtf(LOG_TAG, "WakeLock " + mWakeLock + " not held");
}
}
-}
+
+ @Override
+ public void addDebugLogEntry(@NonNull String logMsg) {
+ SystemClockTime.addDebugLogEntry(logMsg);
+ }
+
+ @Override
+ public void dumpDebugLog(@NonNull PrintWriter printWriter) {
+ SystemClockTime.dump(printWriter);
+ }}
diff --git a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
index 888304aa199b..0ea5f7a105d1 100644
--- a/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
+++ b/services/core/java/com/android/server/timedetector/ServiceConfigAccessorImpl.java
@@ -68,6 +68,15 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
private static final int SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS_DEFAULT = 2 * 1000;
/**
+ * An absolute threshold at/below which the system clock confidence can be upgraded. i.e. if the
+ * detector receives a high-confidence time and the current system clock is +/- this value from
+ * that time and the confidence in the time is low, then the device's confidence in the current
+ * system clock time can be upgraded. This needs to be an amount users would consider
+ * "close enough".
+ */
+ private static final int SYSTEM_CLOCK_CONFIRMATION_THRESHOLD_MILLIS = 1000;
+
+ /**
* By default telephony and network only suggestions are accepted and telephony takes
* precedence over network.
*/
@@ -236,6 +245,8 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
.setAutoDetectionSupported(isAutoDetectionSupported())
.setAutoDetectionEnabledSetting(getAutoDetectionEnabledSetting())
.setSystemClockUpdateThresholdMillis(getSystemClockUpdateThresholdMillis())
+ .setSystemClockConfidenceUpgradeThresholdMillis(
+ getSystemClockConfidenceUpgradeThresholdMillis())
.setAutoSuggestionLowerBound(getAutoSuggestionLowerBound())
.setManualSuggestionLowerBound(timeDetectorHelper.getManualSuggestionLowerBound())
.setSuggestionUpperBound(timeDetectorHelper.getSuggestionUpperBound())
@@ -285,6 +296,10 @@ final class ServiceConfigAccessorImpl implements ServiceConfigAccessor {
return mSystemClockUpdateThresholdMillis;
}
+ private int getSystemClockConfidenceUpgradeThresholdMillis() {
+ return SYSTEM_CLOCK_CONFIRMATION_THRESHOLD_MILLIS;
+ }
+
@NonNull
private Instant getAutoSuggestionLowerBound() {
return mServerFlags.getOptionalInstant(KEY_TIME_DETECTOR_LOWER_BOUND_MILLIS_OVERRIDE)
diff --git a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
index 547cf9d32aa1..fe2760e9ce10 100644
--- a/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
+++ b/services/core/java/com/android/server/timedetector/TimeDetectorStrategyImpl.java
@@ -16,6 +16,7 @@
package com.android.server.timedetector;
+import static com.android.server.SystemClockTime.TIME_CONFIDENCE_HIGH;
import static com.android.server.timedetector.TimeDetectorStrategy.originToString;
import android.annotation.CurrentTimeMillisLong;
@@ -23,7 +24,6 @@ import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
-import android.app.AlarmManager;
import android.app.time.ExternalTimeSuggestion;
import android.app.timedetector.ManualTimeSuggestion;
import android.app.timedetector.TelephonyTimeSuggestion;
@@ -31,24 +31,24 @@ import android.content.Context;
import android.os.Handler;
import android.os.TimestampedValue;
import android.util.IndentingPrintWriter;
-import android.util.LocalLog;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.SystemClockTime;
+import com.android.server.SystemClockTime.TimeConfidence;
import com.android.server.timezonedetector.ArrayMapWithHistory;
import com.android.server.timezonedetector.ConfigurationChangeListener;
import com.android.server.timezonedetector.ReferenceWithHistory;
+import java.io.PrintWriter;
import java.time.Duration;
import java.time.Instant;
import java.util.Arrays;
import java.util.Objects;
/**
- * An implementation of {@link TimeDetectorStrategy} that passes telephony and manual suggestions to
- * {@link AlarmManager}. When there are multiple telephony sources, the one with the lowest ID is
- * used unless the data becomes too stale.
+ * The real implementation of {@link TimeDetectorStrategy}.
*
* <p>Most public methods are marked synchronized to ensure thread safety around internal state.
*/
@@ -84,13 +84,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
*/
private static final int KEEP_SUGGESTION_HISTORY_SIZE = 10;
- /**
- * A log that records the decisions / decision metadata that affected the device's system clock
- * time. This is logged in bug reports to assist with debugging issues with detection.
- */
- @NonNull
- private final LocalLog mTimeChangesLog = new LocalLog(30, false /* useLocalTimestamps */);
-
@NonNull
private final Environment mEnvironment;
@@ -157,11 +150,30 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
@CurrentTimeMillisLong
long systemClockMillis();
- /** Sets the device system clock. The WakeLock must be held. */
- void setSystemClock(@CurrentTimeMillisLong long newTimeMillis);
+ /** Returns the system clock confidence value. */
+ @TimeConfidence int systemClockConfidence();
+
+ /** Sets the device system clock and confidence. The WakeLock must be held. */
+ void setSystemClock(
+ @CurrentTimeMillisLong long newTimeMillis, @TimeConfidence int confidence,
+ @NonNull String logMsg);
+
+ /** Sets the device system clock confidence. The WakeLock must be held. */
+ void setSystemClockConfidence(@TimeConfidence int confidence, @NonNull String logMsg);
/** Release the wake lock acquired by a call to {@link #acquireWakeLock()}. */
void releaseWakeLock();
+
+
+ /**
+ * Adds a standalone entry to the time debug log.
+ */
+ void addDebugLogEntry(@NonNull String logMsg);
+
+ /**
+ * Dumps the time debug log to the supplied {@link PrintWriter}.
+ */
+ void dumpDebugLog(PrintWriter printWriter);
}
static TimeDetectorStrategy create(
@@ -250,7 +262,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
String cause = "Manual time suggestion received: suggestion=" + suggestion;
- return setSystemClockIfRequired(ORIGIN_MANUAL, newUnixEpochTime, cause);
+ return setSystemClockAndConfidenceIfRequired(ORIGIN_MANUAL, newUnixEpochTime, cause);
}
@Override
@@ -318,7 +330,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
String logMsg = "handleConfigurationInternalChanged:"
+ " oldConfiguration=" + mCurrentConfigurationInternal
+ ", newConfiguration=" + currentUserConfig;
- logTimeDetectorChange(logMsg);
+ addDebugLogEntry(logMsg);
mCurrentConfigurationInternal = currentUserConfig;
boolean autoDetectionEnabled =
@@ -335,11 +347,11 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
}
- private void logTimeDetectorChange(@NonNull String logMsg) {
+ private void addDebugLogEntry(@NonNull String logMsg) {
if (DBG) {
Slog.d(LOG_TAG, logMsg);
}
- mTimeChangesLog.log(logMsg);
+ mEnvironment.addDebugLogEntry(logMsg);
}
@Override
@@ -356,10 +368,11 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
long systemClockMillis = mEnvironment.systemClockMillis();
ipw.printf("mEnvironment.systemClockMillis()=%s (%s)\n",
Instant.ofEpochMilli(systemClockMillis), systemClockMillis);
+ ipw.println("mEnvironment.systemClockConfidence()=" + mEnvironment.systemClockConfidence());
ipw.println("Time change log:");
ipw.increaseIndent(); // level 2
- mTimeChangesLog.dump(ipw);
+ SystemClockTime.dump(ipw);
ipw.decreaseIndent(); // level 2
ipw.println("Telephony suggestion history:");
@@ -494,11 +507,6 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
@GuardedBy("this")
private void doAutoTimeDetection(@NonNull String detectionReason) {
- if (!mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior()) {
- // Avoid doing unnecessary work with this (race-prone) check.
- return;
- }
-
// Try the different origins one at a time.
int[] originPriorities = mCurrentConfigurationInternal.getAutoOriginPriorities();
for (int origin : originPriorities) {
@@ -544,7 +552,14 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
// Update the system clock if a good suggestion has been found.
if (newUnixEpochTime != null) {
- setSystemClockIfRequired(origin, newUnixEpochTime, cause);
+ if (mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior()) {
+ setSystemClockAndConfidenceIfRequired(origin, newUnixEpochTime, cause);
+ } else {
+ // An automatically detected time can be used to raise the confidence in the
+ // current time even if the device is set to only allow user input for the time
+ // itself.
+ upgradeSystemClockConfidenceIfRequired(newUnixEpochTime, cause);
+ }
return;
}
}
@@ -718,14 +733,18 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
@GuardedBy("this")
- private boolean setSystemClockIfRequired(
+ private boolean setSystemClockAndConfidenceIfRequired(
@Origin int origin, @NonNull TimestampedValue<Long> time, @NonNull String cause) {
+ // Any time set through this class is inherently high confidence. Either it came directly
+ // from a user, or it was detected automatically.
+ @TimeConfidence final int newTimeConfidence = TIME_CONFIDENCE_HIGH;
boolean isOriginAutomatic = isOriginAutomatic(origin);
if (isOriginAutomatic) {
if (!mCurrentConfigurationInternal.getAutoDetectionEnabledBehavior()) {
if (DBG) {
- Slog.d(LOG_TAG, "Auto time detection is not enabled."
+ Slog.d(LOG_TAG,
+ "Auto time detection is not enabled / no confidence update is needed."
+ " origin=" + originToString(origin)
+ ", time=" + time
+ ", cause=" + cause);
@@ -746,7 +765,57 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
mEnvironment.acquireWakeLock();
try {
- return setSystemClockUnderWakeLock(origin, time, cause);
+ return setSystemClockAndConfidenceUnderWakeLock(origin, time, newTimeConfidence, cause);
+ } finally {
+ mEnvironment.releaseWakeLock();
+ }
+ }
+
+ /**
+ * Upgrades the system clock confidence if the current time matches the supplied auto-detected
+ * time. The method never changes the system clock and it never lowers the confidence. It only
+ * raises the confidence if the supplied time is within the configured threshold of the current
+ * system clock time.
+ */
+ @GuardedBy("this")
+ private void upgradeSystemClockConfidenceIfRequired(
+ @NonNull TimestampedValue<Long> autoDetectedUnixEpochTime, @NonNull String cause) {
+ @TimeConfidence int newTimeConfidence = TIME_CONFIDENCE_HIGH;
+ @TimeConfidence int currentTimeConfidence = mEnvironment.systemClockConfidence();
+ boolean timeNeedsConfirmation = currentTimeConfidence < newTimeConfidence;
+ if (!timeNeedsConfirmation) {
+ return;
+ }
+
+ // All system clock calculation take place under a wake lock.
+ mEnvironment.acquireWakeLock();
+ try {
+ // Check if the specified time matches the current system clock time (closely
+ // enough) to raise the confidence.
+ long elapsedRealtimeMillis = mEnvironment.elapsedRealtimeMillis();
+ long actualSystemClockMillis = mEnvironment.systemClockMillis();
+ long adjustedAutoDetectedUnixEpochMillis = TimeDetectorStrategy.getTimeAt(
+ autoDetectedUnixEpochTime, elapsedRealtimeMillis);
+ long absTimeDifferenceMillis =
+ Math.abs(adjustedAutoDetectedUnixEpochMillis - actualSystemClockMillis);
+ int confidenceUpgradeThresholdMillis =
+ mCurrentConfigurationInternal.getSystemClockConfidenceUpgradeThresholdMillis();
+ boolean updateConfidenceRequired =
+ absTimeDifferenceMillis <= confidenceUpgradeThresholdMillis;
+ if (updateConfidenceRequired) {
+ String logMsg = "Upgrade system clock confidence."
+ + " autoDetectedUnixEpochTime=" + autoDetectedUnixEpochTime
+ + " newTimeConfidence=" + newTimeConfidence
+ + " cause=" + cause
+ + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ + " (old) actualSystemClockMillis=" + actualSystemClockMillis
+ + " currentTimeConfidence=" + currentTimeConfidence;
+ if (DBG) {
+ Slog.d(LOG_TAG, logMsg);
+ }
+
+ mEnvironment.setSystemClockConfidence(newTimeConfidence, logMsg);
+ }
} finally {
mEnvironment.releaseWakeLock();
}
@@ -757,8 +826,9 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
@GuardedBy("this")
- private boolean setSystemClockUnderWakeLock(
- @Origin int origin, @NonNull TimestampedValue<Long> newTime, @NonNull String cause) {
+ private boolean setSystemClockAndConfidenceUnderWakeLock(
+ @Origin int origin, @NonNull TimestampedValue<Long> newTime,
+ @TimeConfidence int newTimeConfidence, @NonNull String cause) {
long elapsedRealtimeMillis = mEnvironment.elapsedRealtimeMillis();
boolean isOriginAutomatic = isOriginAutomatic(origin);
@@ -776,6 +846,7 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
"System clock has not tracked elapsed real time clock. A clock may"
+ " be inaccurate or something unexpectedly set the system"
+ " clock."
+ + " origin=" + originToString(origin)
+ " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ " expectedTimeMillis=" + expectedTimeMillis
+ " actualTimeMillis=" + actualSystemClockMillis
@@ -784,44 +855,72 @@ public final class TimeDetectorStrategyImpl implements TimeDetectorStrategy {
}
}
+ // If the new signal would make sufficient difference to the system clock or mean a change
+ // in confidence then system state must be updated.
+
// Adjust for the time that has elapsed since the signal was received.
long newSystemClockMillis = TimeDetectorStrategy.getTimeAt(newTime, elapsedRealtimeMillis);
-
- // Check if the new signal would make sufficient difference to the system clock. If it's
- // below the threshold then ignore it.
long absTimeDifference = Math.abs(newSystemClockMillis - actualSystemClockMillis);
long systemClockUpdateThreshold =
mCurrentConfigurationInternal.getSystemClockUpdateThresholdMillis();
- if (absTimeDifference < systemClockUpdateThreshold) {
+ boolean updateSystemClockRequired = absTimeDifference >= systemClockUpdateThreshold;
+
+ @TimeConfidence int currentTimeConfidence = mEnvironment.systemClockConfidence();
+ boolean updateConfidenceRequired = newTimeConfidence > currentTimeConfidence;
+
+ if (updateSystemClockRequired) {
+ String logMsg = "Set system clock & confidence."
+ + " origin=" + originToString(origin)
+ + " newTime=" + newTime
+ + " newTimeConfidence=" + newTimeConfidence
+ + " cause=" + cause
+ + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ + " (old) actualSystemClockMillis=" + actualSystemClockMillis
+ + " newSystemClockMillis=" + newSystemClockMillis
+ + " currentTimeConfidence=" + currentTimeConfidence;
+ mEnvironment.setSystemClock(newSystemClockMillis, newTimeConfidence, logMsg);
if (DBG) {
- Slog.d(LOG_TAG, "Not setting system clock. New time and"
- + " system clock are close enough."
- + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ Slog.d(LOG_TAG, logMsg);
+ }
+
+ // CLOCK_PARANOIA : Record the last time this class set the system clock due to an
+ // auto-time signal, or clear the record it is being done manually.
+ if (isOriginAutomatic(origin)) {
+ mLastAutoSystemClockTimeSet = newTime;
+ } else {
+ mLastAutoSystemClockTimeSet = null;
+ }
+ } else if (updateConfidenceRequired) {
+ // Only the confidence needs updating. This path is separate from a system clock update
+ // to deliberately avoid touching the system clock's value when it's not needed. Doing
+ // so could introduce inaccuracies or cause unnecessary wear in RTC hardware or
+ // associated storage.
+ String logMsg = "Set system clock confidence."
+ + " origin=" + originToString(origin)
+ + " newTime=" + newTime
+ + " newTimeConfidence=" + newTimeConfidence
+ + " cause=" + cause
+ + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ + " (old) actualSystemClockMillis=" + actualSystemClockMillis
+ + " newSystemClockMillis=" + newSystemClockMillis
+ + " currentTimeConfidence=" + currentTimeConfidence;
+ if (DBG) {
+ Slog.d(LOG_TAG, logMsg);
+ }
+ mEnvironment.setSystemClockConfidence(newTimeConfidence, logMsg);
+ } else {
+ // Neither clock nor confidence need updating.
+ if (DBG) {
+ Slog.d(LOG_TAG, "Not setting system clock or confidence."
+ + " origin=" + originToString(origin)
+ " newTime=" + newTime
+ + " newTimeConfidence=" + newTimeConfidence
+ " cause=" + cause
+ + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
+ " systemClockUpdateThreshold=" + systemClockUpdateThreshold
- + " absTimeDifference=" + absTimeDifference);
+ + " absTimeDifference=" + absTimeDifference
+ + " currentTimeConfidence=" + currentTimeConfidence);
}
- return true;
- }
-
- mEnvironment.setSystemClock(newSystemClockMillis);
- String logMsg = "Set system clock using time=" + newTime
- + " cause=" + cause
- + " elapsedRealtimeMillis=" + elapsedRealtimeMillis
- + " (old) actualSystemClockMillis=" + actualSystemClockMillis
- + " newSystemClockMillis=" + newSystemClockMillis;
- if (DBG) {
- Slog.d(LOG_TAG, logMsg);
- }
- mTimeChangesLog.log(logMsg);
-
- // CLOCK_PARANOIA : Record the last time this class set the system clock due to an auto-time
- // signal, or clear the record it is being done manually.
- if (isOriginAutomatic(origin)) {
- mLastAutoSystemClockTimeSet = newTime;
- } else {
- mLastAutoSystemClockTimeSet = null;
}
return true;
}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index ffe24c07f1d3..7bc62ec698a3 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -332,8 +332,8 @@ class ActivityClientController extends IActivityClientController.Stub {
}
@Override
- public boolean navigateUpTo(IBinder token, Intent destIntent, int resultCode,
- Intent resultData) {
+ public boolean navigateUpTo(IBinder token, Intent destIntent, String resolvedType,
+ int resultCode, Intent resultData) {
final ActivityRecord r;
synchronized (mGlobalLock) {
r = ActivityRecord.isInRootTaskLocked(token);
@@ -348,7 +348,7 @@ class ActivityClientController extends IActivityClientController.Stub {
synchronized (mGlobalLock) {
return r.getRootTask().navigateUpTo(
- r, destIntent, destGrants, resultCode, resultData, resultGrants);
+ r, destIntent, resolvedType, destGrants, resultCode, resultData, resultGrants);
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 63c6c35a8e1e..62d93ad7d030 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -5278,8 +5278,9 @@ class Task extends TaskFragment {
return false;
}
- boolean navigateUpTo(ActivityRecord srec, Intent destIntent, NeededUriGrants destGrants,
- int resultCode, Intent resultData, NeededUriGrants resultGrants) {
+ boolean navigateUpTo(ActivityRecord srec, Intent destIntent, String resolvedType,
+ NeededUriGrants destGrants, int resultCode, Intent resultData,
+ NeededUriGrants resultGrants) {
if (!srec.attachedToProcess()) {
// Nothing to do if the caller is not attached, because this method should be called
// from an alive activity.
@@ -5348,32 +5349,26 @@ class Task extends TaskFragment {
if (parent != null && foundParentInTask) {
final int callingUid = srec.info.applicationInfo.uid;
- try {
- ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
- destIntent.getComponent(), ActivityManagerService.STOCK_PM_FLAGS,
- srec.mUserId);
- // TODO(b/64750076): Check if calling pid should really be -1.
- final int res = mAtmService.getActivityStartController()
- .obtainStarter(destIntent, "navigateUpTo")
- .setCaller(srec.app.getThread())
- .setActivityInfo(aInfo)
- .setResultTo(parent.token)
- .setIntentGrants(destGrants)
- .setCallingPid(-1)
- .setCallingUid(callingUid)
- .setCallingPackage(srec.packageName)
- .setCallingFeatureId(parent.launchedFromFeatureId)
- .setRealCallingPid(-1)
- .setRealCallingUid(callingUid)
- .setComponentSpecified(true)
- .execute();
- foundParentInTask = isStartResultSuccessful(res);
- if (res == ActivityManager.START_SUCCESS) {
- parent.finishIfPossible(resultCode, resultData, resultGrants,
- "navigate-top", true /* oomAdj */);
- }
- } catch (RemoteException e) {
- foundParentInTask = false;
+ // TODO(b/64750076): Check if calling pid should really be -1.
+ final int res = mAtmService.getActivityStartController()
+ .obtainStarter(destIntent, "navigateUpTo")
+ .setResolvedType(resolvedType)
+ .setUserId(srec.mUserId)
+ .setCaller(srec.app.getThread())
+ .setResultTo(parent.token)
+ .setIntentGrants(destGrants)
+ .setCallingPid(-1)
+ .setCallingUid(callingUid)
+ .setCallingPackage(srec.packageName)
+ .setCallingFeatureId(parent.launchedFromFeatureId)
+ .setRealCallingPid(-1)
+ .setRealCallingUid(callingUid)
+ .setComponentSpecified(true)
+ .execute();
+ foundParentInTask = isStartResultSuccessful(res);
+ if (res == ActivityManager.START_SUCCESS) {
+ parent.finishIfPossible(resultCode, resultData, resultGrants,
+ "navigate-top", true /* oomAdj */);
}
}
Binder.restoreCallingIdentity(origId);
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 5d6ffd8b8ead..7e93d623f3e0 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -53,6 +53,7 @@ cc_library_static {
"com_android_server_soundtrigger_middleware_ExternalCaptureStateTracker.cpp",
"com_android_server_stats_pull_StatsPullAtomService.cpp",
"com_android_server_storage_AppFuseBridge.cpp",
+ "com_android_server_SystemClockTime.cpp",
"com_android_server_SystemServer.cpp",
"com_android_server_tv_TvUinputBridge.cpp",
"com_android_server_tv_TvInputHal.cpp",
diff --git a/services/core/jni/OWNERS b/services/core/jni/OWNERS
index 9abf107c780a..2584b86f53db 100644
--- a/services/core/jni/OWNERS
+++ b/services/core/jni/OWNERS
@@ -12,6 +12,7 @@ per-file com_android_server_power_PowerManagerService.* = michaelwr@google.com,
per-file com_android_server_am_BatteryStatsService.cpp = file:/BATTERY_STATS_OWNERS
per-file Android.bp = file:platform/build/soong:/OWNERS #{LAST_RESORT_SUGGESTION}
+per-file com_android_server_SystemClock* = file:/services/core/java/com/android/server/timedetector/OWNERS
per-file com_android_server_Usb* = file:/services/usb/OWNERS
per-file com_android_server_Vibrator* = file:/services/core/java/com/android/server/vibrator/OWNERS
per-file com_android_server_hdmi_* = file:/core/java/android/hardware/hdmi/OWNERS
diff --git a/services/core/jni/com_android_server_SystemClockTime.cpp b/services/core/jni/com_android_server_SystemClockTime.cpp
new file mode 100644
index 000000000000..9db4c429f0c7
--- /dev/null
+++ b/services/core/jni/com_android_server_SystemClockTime.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SystemClockTime"
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+#include <linux/rtc.h>
+#include <nativehelper/JNIHelp.h>
+#include <utils/Log.h>
+#include <utils/String8.h>
+
+#include "jni.h"
+
+namespace android {
+
+class SystemClockImpl {
+public:
+ SystemClockImpl(const std::string &rtc_dev) : rtc_dev{rtc_dev} {}
+
+ int setTime(struct timeval *tv);
+
+private:
+ std::string rtc_dev;
+};
+
+int SystemClockImpl::setTime(struct timeval *tv) {
+ if (settimeofday(tv, NULL) == -1) {
+ ALOGV("settimeofday() failed: %s", strerror(errno));
+ return -1;
+ }
+
+ android::base::unique_fd fd{open(rtc_dev.c_str(), O_RDWR)};
+ if (!fd.ok()) {
+ ALOGE("Unable to open %s: %s", rtc_dev.c_str(), strerror(errno));
+ return -1;
+ }
+
+ struct tm tm;
+ if (!gmtime_r(&tv->tv_sec, &tm)) {
+ ALOGV("gmtime_r() failed: %s", strerror(errno));
+ return -1;
+ }
+
+ struct rtc_time rtc = {};
+ rtc.tm_sec = tm.tm_sec;
+ rtc.tm_min = tm.tm_min;
+ rtc.tm_hour = tm.tm_hour;
+ rtc.tm_mday = tm.tm_mday;
+ rtc.tm_mon = tm.tm_mon;
+ rtc.tm_year = tm.tm_year;
+ rtc.tm_wday = tm.tm_wday;
+ rtc.tm_yday = tm.tm_yday;
+ rtc.tm_isdst = tm.tm_isdst;
+ if (ioctl(fd, RTC_SET_TIME, &rtc) == -1) {
+ ALOGV("RTC_SET_TIME ioctl failed: %s", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
+static jlong com_android_server_SystemClockTime_init(JNIEnv *, jobject) {
+ // Find the wall clock RTC. We expect this always to be /dev/rtc0, but
+ // check the /dev/rtc symlink first so that legacy devices that don't use
+ // rtc0 can add a symlink rather than need to carry a local patch to this
+ // code.
+ //
+ // TODO: if you're reading this in a world where all devices are using the
+ // GKI, you can remove the readlink and just assume /dev/rtc0.
+ std::string dev_rtc;
+ if (!android::base::Readlink("/dev/rtc", &dev_rtc)) {
+ dev_rtc = "/dev/rtc0";
+ }
+
+ std::unique_ptr<SystemClockImpl> system_clock{new SystemClockImpl(dev_rtc)};
+ return reinterpret_cast<jlong>(system_clock.release());
+}
+
+static jint com_android_server_SystemClockTime_setTime(JNIEnv *, jobject, jlong nativeData,
+ jlong millis) {
+ SystemClockImpl *impl = reinterpret_cast<SystemClockImpl *>(nativeData);
+
+ if (millis <= 0 || millis / 1000LL >= std::numeric_limits<time_t>::max()) {
+ return -1;
+ }
+
+ struct timeval tv;
+ tv.tv_sec = (millis / 1000LL);
+ tv.tv_usec = ((millis % 1000LL) * 1000LL);
+
+ ALOGD("Setting time of day to sec=%ld", tv.tv_sec);
+
+ int ret = impl->setTime(&tv);
+ if (ret < 0) {
+ ALOGW("Unable to set rtc to %ld: %s", tv.tv_sec, strerror(errno));
+ ret = -1;
+ }
+ return ret;
+}
+
+static const JNINativeMethod sMethods[] = {
+ /* name, signature, funcPtr */
+ {"init", "()J", (void *)com_android_server_SystemClockTime_init},
+ {"setTime", "(JJ)I", (void *)com_android_server_SystemClockTime_setTime},
+};
+
+int register_com_android_server_SystemClockTime(JNIEnv *env) {
+ return jniRegisterNativeMethods(env, "com/android/server/SystemClockTime", sMethods,
+ NELEM(sMethods));
+}
+
+} /* namespace android */
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 00bef0935308..00f851f9f4ff 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -65,6 +65,7 @@ int register_android_server_companion_virtual_InputController(JNIEnv* env);
int register_android_server_app_GameManagerService(JNIEnv* env);
int register_com_android_server_wm_TaskFpsCallbackController(JNIEnv* env);
int register_com_android_server_display_DisplayControl(JNIEnv* env);
+int register_com_android_server_SystemClockTime(JNIEnv* env);
};
using namespace android;
@@ -122,5 +123,6 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
register_android_server_app_GameManagerService(env);
register_com_android_server_wm_TaskFpsCallbackController(env);
register_com_android_server_display_DisplayControl(env);
+ register_com_android_server_SystemClockTime(env);
return JNI_VERSION_1_4;
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
index 446317e8829f..830e2ac029c2 100644
--- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java
@@ -168,10 +168,12 @@ import com.android.server.AppStateTracker;
import com.android.server.AppStateTrackerImpl;
import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
+import com.android.server.SystemClockTime.TimeConfidence;
import com.android.server.SystemService;
import com.android.server.pm.permission.PermissionManagerService;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.AndroidPackage;
+import com.android.server.tare.AlarmManagerEconomicPolicy;
import com.android.server.tare.EconomyManagerInternal;
import com.android.server.usage.AppStandbyInternal;
@@ -345,10 +347,6 @@ public class AlarmManagerServiceTest {
}
@Override
- void setKernelTime(long millis) {
- }
-
- @Override
int getSystemUiUid(PackageManagerInternal unused) {
return SYSTEM_UI_UID;
}
@@ -360,7 +358,18 @@ public class AlarmManagerServiceTest {
}
@Override
- long getElapsedRealtime() {
+ void initializeTimeIfRequired() {
+ // No-op
+ }
+
+ @Override
+ void setCurrentTimeMillis(long unixEpochMillis,
+ @TimeConfidence int confidence, String logMsg) {
+ mNowRtcTest = unixEpochMillis;
+ }
+
+ @Override
+ long getElapsedRealtimeMillis() {
return mNowElapsedTest;
}
@@ -650,7 +659,8 @@ public class AlarmManagerServiceTest {
}
private void setTareEnabled(boolean enabled) {
- when(mEconomyManagerInternal.isEnabled()).thenReturn(enabled);
+ when(mEconomyManagerInternal.isEnabled(eq(AlarmManagerEconomicPolicy.POLICY_ALARM)))
+ .thenReturn(enabled);
mService.mConstants.onTareEnabledStateChanged(enabled);
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/CompleteEconomicPolicyTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/CompleteEconomicPolicyTest.java
index 47155a1eadd3..6da4ab714d7a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/tare/CompleteEconomicPolicyTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/tare/CompleteEconomicPolicyTest.java
@@ -25,6 +25,10 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -78,10 +82,13 @@ public class CompleteEconomicPolicyTest {
}
@Override
- boolean isPolicyEnabled(int policy) {
+ boolean isPolicyEnabled(int policy, @Nullable DeviceConfig.Properties properties) {
// Use a limited set of policies so that the test doesn't need to be updated whenever
// a policy is added or removed.
- return policy == EconomicPolicy.POLICY_AM || policy == EconomicPolicy.POLICY_JS;
+ if (policy == EconomicPolicy.POLICY_ALARM || policy == EconomicPolicy.POLICY_JOB) {
+ return super.isPolicyEnabled(policy, properties);
+ }
+ return false;
}
}
@@ -116,10 +123,14 @@ public class CompleteEconomicPolicyTest {
-> mDeviceConfigPropertiesBuilder.build())
.when(() -> DeviceConfig.getProperties(
eq(DeviceConfig.NAMESPACE_TARE), ArgumentMatchers.<String>any()));
+ mDeviceConfigPropertiesBuilder
+ .setBoolean(EconomyManager.KEY_ENABLE_POLICY_ALARM, true)
+ .setBoolean(EconomyManager.KEY_ENABLE_POLICY_JOB_SCHEDULER, true);
// Initialize real objects.
// Capture the listeners.
mEconomicPolicy = new CompleteEconomicPolicy(mIrs, mInjector);
+ mEconomicPolicy.setup(mDeviceConfigPropertiesBuilder.build());
}
@After
@@ -129,6 +140,11 @@ public class CompleteEconomicPolicyTest {
}
}
+ private void setDeviceConfigBoolean(String key, boolean val) {
+ mDeviceConfigPropertiesBuilder.setBoolean(key, val);
+ mEconomicPolicy.setup(mDeviceConfigPropertiesBuilder.build());
+ }
+
private void setDeviceConfigCakes(String key, long valCakes) {
mDeviceConfigPropertiesBuilder.setString(key, valCakes + "c");
mEconomicPolicy.setup(mDeviceConfigPropertiesBuilder.build());
@@ -182,4 +198,52 @@ public class CompleteEconomicPolicyTest {
assertEquals(arcToCake(13), mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted));
assertEquals(arcToCake(5), mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app"));
}
+
+
+ @Test
+ public void testPolicyToggling() {
+ setDeviceConfigBoolean(EconomyManager.KEY_ENABLE_POLICY_ALARM, true);
+ setDeviceConfigBoolean(EconomyManager.KEY_ENABLE_POLICY_JOB_SCHEDULER, false);
+ assertEquals(EconomyManager.DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT_CAKES,
+ mEconomicPolicy.getInitialSatiatedConsumptionLimit());
+ assertEquals(EconomyManager.DEFAULT_AM_HARD_CONSUMPTION_LIMIT_CAKES,
+ mEconomicPolicy.getHardSatiatedConsumptionLimit());
+ final String pkgRestricted = "com.pkg.restricted";
+ when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true);
+ assertEquals(0, mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
+ assertEquals(EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES,
+ mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
+ final String pkgExempted = "com.pkg.exempted";
+ when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true);
+ assertEquals(EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED_CAKES,
+ mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted));
+ assertEquals(EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP_CAKES,
+ mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app"));
+ assertNotNull(mEconomicPolicy.getAction(AlarmManagerEconomicPolicy.ACTION_ALARM_CLOCK));
+ assertNull(mEconomicPolicy.getAction(JobSchedulerEconomicPolicy.ACTION_JOB_LOW_START));
+ assertEquals(EconomicPolicy.POLICY_ALARM, mEconomicPolicy.getEnabledPolicyIds());
+ assertTrue(mEconomicPolicy.isPolicyEnabled(EconomicPolicy.POLICY_ALARM));
+ assertFalse(mEconomicPolicy.isPolicyEnabled(EconomicPolicy.POLICY_JOB));
+
+ setDeviceConfigBoolean(EconomyManager.KEY_ENABLE_POLICY_ALARM, false);
+ setDeviceConfigBoolean(EconomyManager.KEY_ENABLE_POLICY_JOB_SCHEDULER, true);
+ assertEquals(EconomyManager.DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT_CAKES,
+ mEconomicPolicy.getInitialSatiatedConsumptionLimit());
+ assertEquals(EconomyManager.DEFAULT_JS_HARD_CONSUMPTION_LIMIT_CAKES,
+ mEconomicPolicy.getHardSatiatedConsumptionLimit());
+ when(mIrs.isPackageRestricted(anyInt(), eq(pkgRestricted))).thenReturn(true);
+ assertEquals(0, mEconomicPolicy.getMaxSatiatedBalance(0, pkgRestricted));
+ assertEquals(EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES,
+ mEconomicPolicy.getMaxSatiatedBalance(0, "com.any.other.app"));
+ when(mIrs.isPackageExempted(anyInt(), eq(pkgExempted))).thenReturn(true);
+ assertEquals(EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES,
+ mEconomicPolicy.getMinSatiatedBalance(0, pkgExempted));
+ assertEquals(EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES,
+ mEconomicPolicy.getMinSatiatedBalance(0, "com.any.other.app"));
+ assertNull(mEconomicPolicy.getAction(AlarmManagerEconomicPolicy.ACTION_ALARM_CLOCK));
+ assertNotNull(mEconomicPolicy.getAction(JobSchedulerEconomicPolicy.ACTION_JOB_LOW_START));
+ assertEquals(EconomicPolicy.POLICY_JOB, mEconomicPolicy.getEnabledPolicyIds());
+ assertFalse(mEconomicPolicy.isPolicyEnabled(EconomicPolicy.POLICY_ALARM));
+ assertTrue(mEconomicPolicy.isPolicyEnabled(EconomicPolicy.POLICY_JOB));
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
index 4ce268f0dc39..ddfa05cf5a2e 100644
--- a/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/tare/ScribeTest.java
@@ -140,6 +140,8 @@ public class ScribeTest {
report1.numPositiveRegulations = 10;
report1.cumulativeNegativeRegulations = 11;
report1.numNegativeRegulations = 12;
+ report1.screenOffDurationMs = 13;
+ report1.screenOffDischargeMah = 14;
mReports.add(report1);
mScribeUnderTest.writeImmediatelyForTesting();
mScribeUnderTest.loadFromDiskLocked();
@@ -160,6 +162,8 @@ public class ScribeTest {
report2.numPositiveRegulations = 100;
report2.cumulativeNegativeRegulations = 110;
report2.numNegativeRegulations = 120;
+ report2.screenOffDurationMs = 130;
+ report2.screenOffDischargeMah = 140;
mReports.add(report2);
mScribeUnderTest.writeImmediatelyForTesting();
mScribeUnderTest.loadFromDiskLocked();
@@ -385,6 +389,10 @@ public class ScribeTest {
eReport.cumulativeNegativeRegulations, aReport.cumulativeNegativeRegulations);
assertEquals("Reports #" + i + " numNegativeRegulations are not equal",
eReport.numNegativeRegulations, aReport.numNegativeRegulations);
+ assertEquals("Reports #" + i + " screenOffDurationMs are not equal",
+ eReport.screenOffDurationMs, aReport.screenOffDurationMs);
+ assertEquals("Reports #" + i + " screenOffDischargeMah are not equal",
+ eReport.screenOffDischargeMah, aReport.screenOffDischargeMah);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthResultCoordinatorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthResultCoordinatorTest.java
new file mode 100644
index 000000000000..47b4bf547ff8
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthResultCoordinatorTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.hardware.biometrics.BiometricManager;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class AuthResultCoordinatorTest {
+ private AuthResultCoordinator mAuthResultCoordinator;
+
+ @Before
+ public void setUp() throws Exception {
+ mAuthResultCoordinator = new AuthResultCoordinator();
+ }
+
+ @Test
+ public void testDefaultMessage() {
+ checkResult(mAuthResultCoordinator.getResult(),
+ AuthResult.FAILED,
+ BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE);
+ }
+
+ @Test
+ public void testSingleMessageCoordinator() {
+ mAuthResultCoordinator.authenticatedFor(
+ BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE);
+ checkResult(mAuthResultCoordinator.getResult(),
+ AuthResult.AUTHENTICATED,
+ BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE);
+ }
+
+ @Test
+ public void testLockout() {
+ mAuthResultCoordinator.lockedOutFor(
+ BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE);
+ checkResult(mAuthResultCoordinator.getResult(),
+ AuthResult.LOCKED_OUT,
+ BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE);
+ }
+
+ @Test
+ public void testHigherStrengthPrecedence() {
+ mAuthResultCoordinator.authenticatedFor(
+ BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE);
+ mAuthResultCoordinator.authenticatedFor(
+ BiometricManager.Authenticators.BIOMETRIC_WEAK);
+ checkResult(mAuthResultCoordinator.getResult(),
+ AuthResult.AUTHENTICATED,
+ BiometricManager.Authenticators.BIOMETRIC_WEAK);
+
+ mAuthResultCoordinator.authenticatedFor(
+ BiometricManager.Authenticators.BIOMETRIC_STRONG);
+ checkResult(mAuthResultCoordinator.getResult(),
+ AuthResult.AUTHENTICATED,
+ BiometricManager.Authenticators.BIOMETRIC_STRONG);
+ }
+
+ @Test
+ public void testAuthPrecedence() {
+ mAuthResultCoordinator.authenticatedFor(
+ BiometricManager.Authenticators.BIOMETRIC_WEAK);
+ mAuthResultCoordinator.lockedOutFor(
+ BiometricManager.Authenticators.BIOMETRIC_WEAK);
+ checkResult(mAuthResultCoordinator.getResult(),
+ AuthResult.AUTHENTICATED,
+ BiometricManager.Authenticators.BIOMETRIC_WEAK);
+
+ }
+
+ void checkResult(AuthResult res, int status,
+ @BiometricManager.Authenticators.Types int strength) {
+ assertThat(res.getStatus()).isEqualTo(status);
+ assertThat(res.getBiometricStrength()).isEqualTo(strength);
+ }
+
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthSessionCoordinatorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthSessionCoordinatorTest.java
new file mode 100644
index 000000000000..9bb0f58db520
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AuthSessionCoordinatorTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_STRONG;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_WEAK;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+
+@Presubmit
+@SmallTest
+public class AuthSessionCoordinatorTest {
+ private static final int PRIMARY_USER = 0;
+ private static final int SECONDARY_USER = 10;
+
+ private AuthSessionCoordinator mCoordinator;
+
+ @Before
+ public void setUp() throws Exception {
+ mCoordinator = new AuthSessionCoordinator();
+ }
+
+ @Test
+ public void testUserUnlocked() {
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse();
+
+ mCoordinator.authStartedFor(PRIMARY_USER, 1);
+ mCoordinator.authenticatedFor(PRIMARY_USER, BIOMETRIC_WEAK, 1);
+
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse();
+ }
+
+ @Test
+ public void testUserCanAuthDuringLockoutOfSameSession() {
+ mCoordinator.resetLockoutFor(PRIMARY_USER, BIOMETRIC_STRONG);
+
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue();
+
+ mCoordinator.authStartedFor(PRIMARY_USER, 1);
+ mCoordinator.authStartedFor(PRIMARY_USER, 2);
+ mCoordinator.lockedOutFor(PRIMARY_USER, BIOMETRIC_WEAK, 2);
+
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue();
+ }
+
+ @Test
+ public void testMultiUserAuth() {
+ mCoordinator.resetLockoutFor(PRIMARY_USER, BIOMETRIC_STRONG);
+
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue();
+
+ assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_CONVENIENCE)).isFalse();
+ assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_WEAK)).isFalse();
+ assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_STRONG)).isFalse();
+
+ mCoordinator.authStartedFor(PRIMARY_USER, 1);
+ mCoordinator.authStartedFor(PRIMARY_USER, 2);
+ mCoordinator.lockedOutFor(PRIMARY_USER, BIOMETRIC_WEAK, 2);
+
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue();
+ assertThat(mCoordinator.getCanAuthFor(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue();
+
+ assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_CONVENIENCE)).isFalse();
+ assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_WEAK)).isFalse();
+ assertThat(mCoordinator.getCanAuthFor(SECONDARY_USER, BIOMETRIC_STRONG)).isFalse();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/MultiBiometricLockoutStateTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/MultiBiometricLockoutStateTest.java
new file mode 100644
index 000000000000..8baa1ce3f6c6
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/MultiBiometricLockoutStateTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors;
+
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_STRONG;
+import static android.hardware.biometrics.BiometricManager.Authenticators.BIOMETRIC_WEAK;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.platform.test.annotations.Presubmit;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@Presubmit
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class MultiBiometricLockoutStateTest {
+ private static final int PRIMARY_USER = 0;
+ private MultiBiometricLockoutState mCoordinator;
+
+ private void unlockAllBiometrics() {
+ unlockAllBiometrics(mCoordinator, PRIMARY_USER);
+ }
+
+ private void lockoutAllBiometrics() {
+ lockoutAllBiometrics(mCoordinator, PRIMARY_USER);
+ }
+
+ private static void unlockAllBiometrics(MultiBiometricLockoutState coordinator, int userId) {
+ coordinator.onUserUnlocked(userId, BIOMETRIC_STRONG);
+ assertThat(coordinator.canUserAuthenticate(userId, BIOMETRIC_STRONG)).isTrue();
+ assertThat(coordinator.canUserAuthenticate(userId, BIOMETRIC_WEAK)).isTrue();
+ assertThat(coordinator.canUserAuthenticate(userId, BIOMETRIC_CONVENIENCE)).isTrue();
+ }
+
+ private static void lockoutAllBiometrics(MultiBiometricLockoutState coordinator, int userId) {
+ coordinator.onUserLocked(userId, BIOMETRIC_STRONG);
+ assertThat(coordinator.canUserAuthenticate(userId, BIOMETRIC_STRONG)).isFalse();
+ assertThat(coordinator.canUserAuthenticate(userId, BIOMETRIC_WEAK)).isFalse();
+ assertThat(coordinator.canUserAuthenticate(userId, BIOMETRIC_CONVENIENCE)).isFalse();
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ mCoordinator = new MultiBiometricLockoutState();
+ }
+
+ @Test
+ public void testInitialStateLockedOut() {
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse();
+ }
+
+ @Test
+ public void testConvenienceLockout() {
+ unlockAllBiometrics();
+ mCoordinator.onUserLocked(PRIMARY_USER, BIOMETRIC_CONVENIENCE);
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse();
+ }
+
+ @Test
+ public void testWeakLockout() {
+ unlockAllBiometrics();
+ mCoordinator.onUserLocked(PRIMARY_USER, BIOMETRIC_WEAK);
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse();
+ }
+
+ @Test
+ public void testStrongLockout() {
+ unlockAllBiometrics();
+ mCoordinator.onUserLocked(PRIMARY_USER, BIOMETRIC_STRONG);
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isFalse();
+ }
+
+ @Test
+ public void testConvenienceUnlock() {
+ lockoutAllBiometrics();
+ mCoordinator.onUserUnlocked(PRIMARY_USER, BIOMETRIC_CONVENIENCE);
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isFalse();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue();
+ }
+
+ @Test
+ public void testWeakUnlock() {
+ lockoutAllBiometrics();
+ mCoordinator.onUserUnlocked(PRIMARY_USER, BIOMETRIC_WEAK);
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isFalse();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue();
+ }
+
+ @Test
+ public void testStrongUnlock() {
+ lockoutAllBiometrics();
+ mCoordinator.onUserUnlocked(PRIMARY_USER, BIOMETRIC_STRONG);
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_STRONG)).isTrue();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_WEAK)).isTrue();
+ assertThat(mCoordinator.canUserAuthenticate(PRIMARY_USER, BIOMETRIC_CONVENIENCE)).isTrue();
+ }
+
+ @Test
+ public void multiUser_userOneDoesNotAffectUserTwo() {
+ final int userOne = 1;
+ final int userTwo = 2;
+ MultiBiometricLockoutState coordinator = new MultiBiometricLockoutState();
+ lockoutAllBiometrics(coordinator, userOne);
+ lockoutAllBiometrics(coordinator, userTwo);
+
+ coordinator.onUserUnlocked(userOne, BIOMETRIC_WEAK);
+ assertThat(coordinator.canUserAuthenticate(userOne, BIOMETRIC_STRONG)).isFalse();
+ assertThat(coordinator.canUserAuthenticate(userOne, BIOMETRIC_WEAK)).isTrue();
+ assertThat(coordinator.canUserAuthenticate(userOne, BIOMETRIC_CONVENIENCE)).isTrue();
+
+ assertThat(coordinator.canUserAuthenticate(userTwo, BIOMETRIC_STRONG)).isFalse();
+ assertThat(coordinator.canUserAuthenticate(userTwo, BIOMETRIC_WEAK)).isFalse();
+ assertThat(coordinator.canUserAuthenticate(userTwo, BIOMETRIC_CONVENIENCE)).isFalse();
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/tare/AnalystTest.java b/services/tests/servicestests/src/com/android/server/tare/AnalystTest.java
index 2b527a261ae1..a603b93ab307 100644
--- a/services/tests/servicestests/src/com/android/server/tare/AnalystTest.java
+++ b/services/tests/servicestests/src/com/android/server/tare/AnalystTest.java
@@ -19,10 +19,14 @@ package com.android.server.tare;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.app.IBatteryStats;
+
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,20 +49,20 @@ public class AnalystTest {
final Analyst analyst = new Analyst();
Analyst.Report expected = new Analyst.Report();
- expected.currentBatteryLevel = 55;
- analyst.noteBatteryLevelChange(55);
+ expected.currentBatteryLevel = 75;
+ analyst.noteBatteryLevelChange(75);
assertEquals(1, analyst.getReports().size());
assertReportsEqual(expected, analyst.getReports().get(0));
// Discharging
analyst.noteBatteryLevelChange(54);
expected.currentBatteryLevel = 54;
- expected.cumulativeBatteryDischarge = 1;
+ expected.cumulativeBatteryDischarge = 21;
assertEquals(1, analyst.getReports().size());
assertReportsEqual(expected, analyst.getReports().get(0));
analyst.noteBatteryLevelChange(50);
expected.currentBatteryLevel = 50;
- expected.cumulativeBatteryDischarge = 5;
+ expected.cumulativeBatteryDischarge = 25;
assertEquals(1, analyst.getReports().size());
assertReportsEqual(expected, analyst.getReports().get(0));
@@ -87,27 +91,53 @@ public class AnalystTest {
}
@Test
- public void testTransaction_PeriodChange() {
- final Analyst analyst = new Analyst();
+ public void testTransaction_PeriodChange() throws Exception {
+ IBatteryStats iBatteryStats = mock(IBatteryStats.class);
+ final Analyst analyst = new Analyst(iBatteryStats);
+ // Reset from enough discharge.
Analyst.Report expected = new Analyst.Report();
- expected.currentBatteryLevel = 55;
- analyst.noteBatteryLevelChange(55);
+ expected.currentBatteryLevel = 75;
+ analyst.noteBatteryLevelChange(75);
runTestTransactions(analyst, expected, 1);
expected.currentBatteryLevel = 49;
- expected.cumulativeBatteryDischarge = 6;
+ expected.cumulativeBatteryDischarge = 26;
analyst.noteBatteryLevelChange(49);
runTestTransactions(analyst, expected, 1);
expected = new Analyst.Report();
- expected.currentBatteryLevel = 100;
- analyst.noteBatteryLevelChange(100);
+ expected.currentBatteryLevel = 90;
+ analyst.noteBatteryLevelChange(90);
expected.cumulativeBatteryDischarge = 0;
runTestTransactions(analyst, expected, 2);
+
+ // Reset from report being long enough.
+ doReturn(Analyst.MIN_REPORT_DURATION_FOR_RESET)
+ .when(iBatteryStats).computeBatteryScreenOffRealtimeMs();
+ expected.currentBatteryLevel = 85;
+ analyst.noteBatteryLevelChange(85);
+ expected.cumulativeBatteryDischarge = 5;
+ expected.screenOffDurationMs = Analyst.MIN_REPORT_DURATION_FOR_RESET;
+
+ runTestTransactions(analyst, expected, 2);
+
+ expected.currentBatteryLevel = 79;
+ analyst.noteBatteryLevelChange(79);
+ expected.cumulativeBatteryDischarge = 11;
+
+ runTestTransactions(analyst, expected, 2);
+
+ expected = new Analyst.Report();
+ expected.currentBatteryLevel = 80;
+ analyst.noteBatteryLevelChange(80);
+ expected.cumulativeBatteryDischarge = 0;
+ expected.screenOffDurationMs = 0;
+
+ runTestTransactions(analyst, expected, 3);
}
private void runTestTransactions(Analyst analyst, Analyst.Report lastExpectedReport,
@@ -223,6 +253,8 @@ public class AnalystTest {
assertEquals(expected.numPositiveRegulations, actual.numPositiveRegulations);
assertEquals(expected.cumulativeNegativeRegulations, actual.cumulativeNegativeRegulations);
assertEquals(expected.numNegativeRegulations, actual.numNegativeRegulations);
+ assertEquals(expected.screenOffDurationMs, actual.screenOffDurationMs);
+ assertEquals(expected.screenOffDischargeMah, actual.screenOffDischargeMah);
}
private void assertReportListsEqual(List<Analyst.Report> expected,
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index 1aea6727d3a1..060c31f2985e 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -16,6 +16,8 @@
package com.android.server.timedetector;
+import static com.android.server.SystemClockTime.TIME_CONFIDENCE_HIGH;
+import static com.android.server.SystemClockTime.TIME_CONFIDENCE_LOW;
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_EXTERNAL;
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_GNSS;
import static com.android.server.timedetector.TimeDetectorStrategy.ORIGIN_NETWORK;
@@ -35,6 +37,7 @@ import android.os.TimestampedValue;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.SystemClockTime.TimeConfidence;
import com.android.server.timedetector.TimeDetectorStrategy.Origin;
import com.android.server.timezonedetector.ConfigurationChangeListener;
@@ -42,6 +45,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.io.PrintWriter;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
@@ -86,6 +90,7 @@ public class TimeDetectorStrategyImplTest {
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(
ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
+ .setSystemClockUpdateThresholdMillis(TIME_CONFIDENCE_HIGH)
.setAutoSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
.setManualSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
.setSuggestionUpperBound(DEFAULT_SUGGESTION_UPPER_BOUND)
@@ -99,6 +104,7 @@ public class TimeDetectorStrategyImplTest {
.setAutoDetectionSupported(true)
.setSystemClockUpdateThresholdMillis(
ARBITRARY_SYSTEM_CLOCK_UPDATE_THRESHOLD_MILLIS)
+ .setSystemClockUpdateThresholdMillis(TIME_CONFIDENCE_HIGH)
.setAutoSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
.setManualSuggestionLowerBound(DEFAULT_SUGGESTION_LOWER_BOUND)
.setSuggestionUpperBound(DEFAULT_SUGGESTION_UPPER_BOUND)
@@ -112,12 +118,14 @@ public class TimeDetectorStrategyImplTest {
public void setUp() {
mFakeEnvironment = new FakeEnvironment();
mFakeEnvironment.initializeConfig(CONFIG_AUTO_DISABLED);
- mFakeEnvironment.initializeFakeClocks(ARBITRARY_CLOCK_INITIALIZATION_INFO);
+ mFakeEnvironment.initializeFakeClocks(
+ ARBITRARY_CLOCK_INITIALIZATION_INFO, TIME_CONFIDENCE_LOW);
}
@Test
public void testSuggestTelephonyTime_autoTimeEnabled() {
- Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
+ Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
int slotIndex = ARBITRARY_SLOT_INDEX;
Instant testTime = ARBITRARY_TEST_TIME;
@@ -129,18 +137,21 @@ public class TimeDetectorStrategyImplTest {
long expectedSystemClockMillis =
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
- script.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
+ script.verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
+ .verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion);
}
@Test
public void testSuggestTelephonyTime_emptySuggestionIgnored() {
- Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
+ Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
int slotIndex = ARBITRARY_SLOT_INDEX;
TelephonyTimeSuggestion timeSuggestion =
script.generateTelephonyTimeSuggestion(slotIndex, null);
script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, null);
}
@@ -278,17 +289,115 @@ public class TimeDetectorStrategyImplTest {
}
}
+ /**
+ * If an auto suggested time matches the current system clock, the confidence in the current
+ * system clock is raised even when auto time is disabled. The system clock itself must not be
+ * changed.
+ */
@Test
- public void testSuggestTelephonyTime_autoTimeDisabled() {
- Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
+ public void testSuggestTelephonyTime_autoTimeDisabled_suggestionMatchesSystemClock() {
+ TimestampedValue<Instant> initialClockTime = ARBITRARY_CLOCK_INITIALIZATION_INFO;
+ final int confidenceUpgradeThresholdMillis = 1000;
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setSystemClockConfidenceUpgradeThresholdMillis(
+ confidenceUpgradeThresholdMillis)
+ .build();
+ Script script = new Script()
+ .pokeFakeClocks(initialClockTime, TIME_CONFIDENCE_LOW)
+ .simulateConfigurationInternalChange(configInternal);
int slotIndex = ARBITRARY_SLOT_INDEX;
- TelephonyTimeSuggestion timeSuggestion =
- script.generateTelephonyTimeSuggestion(slotIndex, ARBITRARY_TEST_TIME);
- script.simulateTimePassing()
- .simulateTelephonyTimeSuggestion(timeSuggestion)
- .verifySystemClockWasNotSetAndResetCallTracking()
- .assertLatestTelephonySuggestion(slotIndex, timeSuggestion);
+
+ script.simulateTimePassing();
+ long timeElapsedMillis =
+ script.peekElapsedRealtimeMillis() - initialClockTime.getReferenceTimeMillis();
+
+ // Create a suggestion time that approximately matches the current system clock.
+ Instant suggestionInstant = initialClockTime.getValue()
+ .plusMillis(timeElapsedMillis)
+ .plusMillis(confidenceUpgradeThresholdMillis);
+ TimestampedValue<Long> matchingClockTime = new TimestampedValue<>(
+ script.peekElapsedRealtimeMillis(),
+ suggestionInstant.toEpochMilli());
+ TelephonyTimeSuggestion timeSuggestion = new TelephonyTimeSuggestion.Builder(slotIndex)
+ .setUnixEpochTime(matchingClockTime)
+ .build();
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ /**
+ * If an auto suggested time doesn't match the current system clock, the confidence in the
+ * current system clock will stay where it is. The system clock itself must not be changed.
+ */
+ @Test
+ public void testSuggestTelephonyTime_autoTimeDisabled_suggestionMismatchesSystemClock() {
+ TimestampedValue<Instant> initialClockTime = ARBITRARY_CLOCK_INITIALIZATION_INFO;
+ final int confidenceUpgradeThresholdMillis = 1000;
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setSystemClockConfidenceUpgradeThresholdMillis(
+ confidenceUpgradeThresholdMillis)
+ .build();
+ Script script = new Script().pokeFakeClocks(initialClockTime, TIME_CONFIDENCE_LOW)
+ .simulateConfigurationInternalChange(configInternal);
+
+ int slotIndex = ARBITRARY_SLOT_INDEX;
+
+ script.simulateTimePassing();
+ long timeElapsedMillis =
+ script.peekElapsedRealtimeMillis() - initialClockTime.getReferenceTimeMillis();
+
+ // Create a suggestion time that doesn't match the current system clock closely enough.
+ Instant suggestionInstant = initialClockTime.getValue()
+ .plusMillis(timeElapsedMillis)
+ .plusMillis(confidenceUpgradeThresholdMillis + 1);
+ TimestampedValue<Long> mismatchingClockTime = new TimestampedValue<>(
+ script.peekElapsedRealtimeMillis(),
+ suggestionInstant.toEpochMilli());
+ TelephonyTimeSuggestion timeSuggestion = new TelephonyTimeSuggestion.Builder(slotIndex)
+ .setUnixEpochTime(mismatchingClockTime)
+ .build();
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
+ .verifySystemClockWasNotSetAndResetCallTracking();
+ }
+
+ /**
+ * If a suggested time doesn't match the current system clock, the confidence in the current
+ * system clock will not drop.
+ */
+ @Test
+ public void testSuggestTelephonyTime_autoTimeDisabled_suggestionMismatchesSystemClock2() {
+ TimestampedValue<Instant> initialClockTime = ARBITRARY_CLOCK_INITIALIZATION_INFO;
+ final int confidenceUpgradeThresholdMillis = 1000;
+ ConfigurationInternal configInternal =
+ new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
+ .setSystemClockConfidenceUpgradeThresholdMillis(
+ confidenceUpgradeThresholdMillis)
+ .build();
+ Script script = new Script().pokeFakeClocks(initialClockTime, TIME_CONFIDENCE_HIGH)
+ .simulateConfigurationInternalChange(configInternal);
+
+ int slotIndex = ARBITRARY_SLOT_INDEX;
+
+ script.simulateTimePassing();
+ long timeElapsedMillis =
+ script.peekElapsedRealtimeMillis() - initialClockTime.getReferenceTimeMillis();
+
+ // Create a suggestion time that doesn't closely match the current system clock.
+ Instant initialClockInstant = initialClockTime.getValue();
+ TimestampedValue<Long> mismatchingClockTime = new TimestampedValue<>(
+ script.peekElapsedRealtimeMillis(),
+ initialClockInstant.plusMillis(timeElapsedMillis + 1_000_000).toEpochMilli());
+ TelephonyTimeSuggestion timeSuggestion = new TelephonyTimeSuggestion.Builder(slotIndex)
+ .setUnixEpochTime(mismatchingClockTime)
+ .build();
+ script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
+ .verifySystemClockWasNotSetAndResetCallTracking();
}
@Test
@@ -298,7 +407,8 @@ public class TimeDetectorStrategyImplTest {
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
.setSystemClockUpdateThresholdMillis(systemClockUpdateThresholdMillis)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant testTime = ARBITRARY_TEST_TIME;
int slotIndex = ARBITRARY_SLOT_INDEX;
@@ -311,6 +421,7 @@ public class TimeDetectorStrategyImplTest {
script.simulateTimePassing();
long expectedSystemClockMillis1 = script.calculateTimeInMillisForNow(unixEpochTime1);
script.simulateTelephonyTimeSuggestion(timeSuggestion1)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
@@ -327,6 +438,7 @@ public class TimeDetectorStrategyImplTest {
TelephonyTimeSuggestion timeSuggestion2 =
createTelephonyTimeSuggestion(slotIndex, unixEpochTime2);
script.simulateTelephonyTimeSuggestion(timeSuggestion2)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
@@ -339,6 +451,7 @@ public class TimeDetectorStrategyImplTest {
TelephonyTimeSuggestion timeSuggestion3 =
createTelephonyTimeSuggestion(slotIndex, unixEpochTime3);
script.simulateTelephonyTimeSuggestion(timeSuggestion3)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
@@ -350,6 +463,7 @@ public class TimeDetectorStrategyImplTest {
TelephonyTimeSuggestion timeSuggestion4 =
createTelephonyTimeSuggestion(slotIndex, unixEpochTime4);
script.simulateTelephonyTimeSuggestion(timeSuggestion4)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis4)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion4);
}
@@ -362,7 +476,8 @@ public class TimeDetectorStrategyImplTest {
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
.setSystemClockUpdateThresholdMillis(systemClockUpdateThresholdMillis)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
int slotIndex = ARBITRARY_SLOT_INDEX;
Instant testTime = ARBITRARY_TEST_TIME;
@@ -376,6 +491,7 @@ public class TimeDetectorStrategyImplTest {
// Simulate the time signal being received. It should not be used because auto time
// detection is off but it should be recorded.
script.simulateTelephonyTimeSuggestion(timeSuggestion1)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
@@ -386,11 +502,13 @@ public class TimeDetectorStrategyImplTest {
// Turn on auto time detection.
script.simulateAutoTimeDetectionToggle()
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis1)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
// Turn off auto time detection.
script.simulateAutoTimeDetectionToggle()
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion1);
@@ -408,18 +526,21 @@ public class TimeDetectorStrategyImplTest {
// The new time, though valid, should not be set in the system clock because auto time is
// disabled.
script.simulateTelephonyTimeSuggestion(timeSuggestion2)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion2);
// Turn on auto time detection.
script.simulateAutoTimeDetectionToggle()
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis2)
.assertLatestTelephonySuggestion(slotIndex, timeSuggestion2);
}
@Test
public void testSuggestTelephonyTime_maxSuggestionAge() {
- Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
+ Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
int slotIndex = ARBITRARY_SLOT_INDEX;
Instant testTime = ARBITRARY_TEST_TIME;
@@ -431,6 +552,7 @@ public class TimeDetectorStrategyImplTest {
long expectedSystemClockMillis =
script.calculateTimeInMillisForNow(telephonySuggestion.getUnixEpochTime());
script.simulateTelephonyTimeSuggestion(telephonySuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(
expectedSystemClockMillis /* expectedNetworkBroadcast */)
.assertLatestTelephonySuggestion(slotIndex, telephonySuggestion);
@@ -442,7 +564,7 @@ public class TimeDetectorStrategyImplTest {
script.simulateTimePassing(TimeDetectorStrategyImpl.MAX_SUGGESTION_TIME_AGE_MILLIS);
// Look inside and check what the strategy considers the current best telephony suggestion.
- // It should still be the, it's just no longer used.
+ // It should still be there, it's just no longer used.
assertNull(script.peekBestTelephonySuggestion());
script.assertLatestTelephonySuggestion(slotIndex, telephonySuggestion);
}
@@ -454,12 +576,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_TELEPHONY)
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
TelephonyTimeSuggestion timeSuggestion =
script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, belowLowerBound);
script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -470,12 +594,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_TELEPHONY)
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
TelephonyTimeSuggestion timeSuggestion =
script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, aboveLowerBound);
script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
}
@@ -486,12 +612,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_TELEPHONY)
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
TelephonyTimeSuggestion timeSuggestion =
script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, aboveUpperBound);
script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -502,18 +630,21 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_TELEPHONY)
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
TelephonyTimeSuggestion timeSuggestion =
script.generateTelephonyTimeSuggestion(ARBITRARY_SLOT_INDEX, belowUpperBound);
script.simulateTelephonyTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
}
@Test
public void testSuggestManualTime_autoTimeDisabled() {
- Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED);
+ Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_DISABLED)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
ManualTimeSuggestion timeSuggestion =
script.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
@@ -524,12 +655,14 @@ public class TimeDetectorStrategyImplTest {
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
script.simulateManualTimeSuggestion(
ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@Test
public void testSuggestManualTime_retainsAutoSignal() {
- Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
+ Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
int slotIndex = ARBITRARY_SLOT_INDEX;
@@ -544,6 +677,7 @@ public class TimeDetectorStrategyImplTest {
long expectedAutoClockMillis =
script.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUnixEpochTime());
script.simulateTelephonyTimeSuggestion(telephonyTimeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
@@ -552,6 +686,7 @@ public class TimeDetectorStrategyImplTest {
// Switch to manual.
script.simulateAutoTimeDetectionToggle()
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
@@ -568,6 +703,7 @@ public class TimeDetectorStrategyImplTest {
script.calculateTimeInMillisForNow(manualTimeSuggestion.getUnixEpochTime());
script.simulateManualTimeSuggestion(
ARBITRARY_USER_ID, manualTimeSuggestion, true /* expectedResult */)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(expectedManualClockMillis)
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
@@ -580,17 +716,20 @@ public class TimeDetectorStrategyImplTest {
expectedAutoClockMillis =
script.calculateTimeInMillisForNow(telephonyTimeSuggestion.getUnixEpochTime());
script.verifySystemClockWasSetAndResetCallTracking(expectedAutoClockMillis)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
// Switch back to manual - nothing should happen to the clock.
script.simulateAutoTimeDetectionToggle()
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasNotSetAndResetCallTracking()
.assertLatestTelephonySuggestion(slotIndex, telephonyTimeSuggestion);
}
@Test
public void testSuggestManualTime_isIgnored_whenAutoTimeEnabled() {
- Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED);
+ Script script = new Script().simulateConfigurationInternalChange(CONFIG_AUTO_ENABLED)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
ManualTimeSuggestion timeSuggestion =
script.generateManualTimeSuggestion(ARBITRARY_TEST_TIME);
@@ -598,6 +737,7 @@ public class TimeDetectorStrategyImplTest {
script.simulateTimePassing()
.simulateManualTimeSuggestion(
ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -607,12 +747,14 @@ public class TimeDetectorStrategyImplTest {
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveUpperBound);
script.simulateManualTimeSuggestion(
ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -622,12 +764,14 @@ public class TimeDetectorStrategyImplTest {
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowUpperBound);
script.simulateManualTimeSuggestion(
ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
}
@@ -637,12 +781,14 @@ public class TimeDetectorStrategyImplTest {
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
.setManualSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(belowLowerBound);
script.simulateManualTimeSuggestion(
ARBITRARY_USER_ID, timeSuggestion, false /* expectedResult */)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -652,12 +798,14 @@ public class TimeDetectorStrategyImplTest {
new ConfigurationInternal.Builder(CONFIG_AUTO_DISABLED)
.setManualSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
ManualTimeSuggestion timeSuggestion = script.generateManualTimeSuggestion(aboveLowerBound);
script.simulateManualTimeSuggestion(
ARBITRARY_USER_ID, timeSuggestion, true /* expectedResult */)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
}
@@ -667,7 +815,8 @@ public class TimeDetectorStrategyImplTest {
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
.setOriginPriorities(ORIGIN_NETWORK)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
NetworkTimeSuggestion timeSuggestion =
script.generateNetworkTimeSuggestion(ARBITRARY_TEST_TIME);
@@ -677,6 +826,7 @@ public class TimeDetectorStrategyImplTest {
long expectedSystemClockMillis =
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@@ -703,12 +853,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_NETWORK)
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
NetworkTimeSuggestion timeSuggestion =
script.generateNetworkTimeSuggestion(belowLowerBound);
script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -719,12 +871,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_NETWORK)
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
NetworkTimeSuggestion timeSuggestion =
script.generateNetworkTimeSuggestion(aboveLowerBound);
script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
}
@@ -735,12 +889,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_NETWORK)
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
NetworkTimeSuggestion timeSuggestion =
script.generateNetworkTimeSuggestion(aboveUpperBound);
script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -751,12 +907,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_NETWORK)
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
NetworkTimeSuggestion timeSuggestion =
script.generateNetworkTimeSuggestion(belowUpperBound);
script.simulateNetworkTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
}
@@ -766,7 +924,8 @@ public class TimeDetectorStrategyImplTest {
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
.setOriginPriorities(ORIGIN_GNSS)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
GnssTimeSuggestion timeSuggestion =
script.generateGnssTimeSuggestion(ARBITRARY_TEST_TIME);
@@ -776,6 +935,7 @@ public class TimeDetectorStrategyImplTest {
long expectedSystemClockMillis =
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@@ -802,12 +962,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_GNSS)
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
GnssTimeSuggestion timeSuggestion =
script.generateGnssTimeSuggestion(belowLowerBound);
script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -818,12 +980,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_GNSS)
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
GnssTimeSuggestion timeSuggestion =
script.generateGnssTimeSuggestion(aboveLowerBound);
script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
}
@@ -834,12 +998,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_GNSS)
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
GnssTimeSuggestion timeSuggestion =
script.generateGnssTimeSuggestion(aboveUpperBound);
script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -850,12 +1016,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_GNSS)
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
GnssTimeSuggestion timeSuggestion =
script.generateGnssTimeSuggestion(belowUpperBound);
script.simulateGnssTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
}
@@ -865,7 +1033,8 @@ public class TimeDetectorStrategyImplTest {
new ConfigurationInternal.Builder(CONFIG_AUTO_ENABLED)
.setOriginPriorities(ORIGIN_EXTERNAL)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
ExternalTimeSuggestion timeSuggestion =
script.generateExternalTimeSuggestion(ARBITRARY_TEST_TIME);
@@ -875,6 +1044,7 @@ public class TimeDetectorStrategyImplTest {
long expectedSystemClockMillis =
script.calculateTimeInMillisForNow(timeSuggestion.getUnixEpochTime());
script.simulateExternalTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(expectedSystemClockMillis);
}
@@ -901,12 +1071,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_EXTERNAL)
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant belowLowerBound = TEST_SUGGESTION_LOWER_BOUND.minusSeconds(1);
ExternalTimeSuggestion timeSuggestion =
script.generateExternalTimeSuggestion(belowLowerBound);
script.simulateExternalTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -917,12 +1089,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_EXTERNAL)
.setAutoSuggestionLowerBound(TEST_SUGGESTION_LOWER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant aboveLowerBound = TEST_SUGGESTION_LOWER_BOUND.plusSeconds(1);
ExternalTimeSuggestion timeSuggestion =
script.generateExternalTimeSuggestion(aboveLowerBound);
script.simulateExternalTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(aboveLowerBound.toEpochMilli());
}
@@ -933,12 +1107,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_EXTERNAL)
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant aboveUpperBound = TEST_SUGGESTION_UPPER_BOUND.plusSeconds(1);
ExternalTimeSuggestion timeSuggestion =
script.generateExternalTimeSuggestion(aboveUpperBound);
script.simulateExternalTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW)
.verifySystemClockWasNotSetAndResetCallTracking();
}
@@ -949,12 +1125,14 @@ public class TimeDetectorStrategyImplTest {
.setOriginPriorities(ORIGIN_EXTERNAL)
.setSuggestionUpperBound(TEST_SUGGESTION_UPPER_BOUND)
.build();
- Script script = new Script().simulateConfigurationInternalChange(configInternal);
+ Script script = new Script().simulateConfigurationInternalChange(configInternal)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_LOW);
Instant belowUpperBound = TEST_SUGGESTION_UPPER_BOUND.minusSeconds(1);
ExternalTimeSuggestion timeSuggestion =
script.generateExternalTimeSuggestion(belowUpperBound);
script.simulateExternalTimeSuggestion(timeSuggestion)
+ .verifySystemClockConfidence(TIME_CONFIDENCE_HIGH)
.verifySystemClockWasSetAndResetCallTracking(belowUpperBound.toEpochMilli());
}
@@ -1472,6 +1650,7 @@ public class TimeDetectorStrategyImplTest {
private boolean mWakeLockAcquired;
private long mElapsedRealtimeMillis;
private long mSystemClockMillis;
+ private int mSystemClockConfidence = TIME_CONFIDENCE_LOW;
private ConfigurationChangeListener mConfigurationInternalChangeListener;
// Tracking operations.
@@ -1481,9 +1660,10 @@ public class TimeDetectorStrategyImplTest {
mConfigurationInternal = configurationInternal;
}
- public void initializeFakeClocks(TimestampedValue<Instant> timeInfo) {
+ public void initializeFakeClocks(
+ TimestampedValue<Instant> timeInfo, @TimeConfidence int timeConfidence) {
pokeElapsedRealtimeMillis(timeInfo.getReferenceTimeMillis());
- pokeSystemClockMillis(timeInfo.getValue().toEpochMilli());
+ pokeSystemClockMillis(timeInfo.getValue().toEpochMilli(), timeConfidence);
}
@Override
@@ -1515,10 +1695,23 @@ public class TimeDetectorStrategyImplTest {
}
@Override
- public void setSystemClock(long newTimeMillis) {
+ public @TimeConfidence int systemClockConfidence() {
+ return mSystemClockConfidence;
+ }
+
+ @Override
+ public void setSystemClock(
+ long newTimeMillis, @TimeConfidence int confidence, String logMsg) {
assertWakeLockAcquired();
mSystemClockWasSet = true;
mSystemClockMillis = newTimeMillis;
+ mSystemClockConfidence = confidence;
+ }
+
+ @Override
+ public void setSystemClockConfidence(@TimeConfidence int confidence, String logMsg) {
+ assertWakeLockAcquired();
+ mSystemClockConfidence = confidence;
}
@Override
@@ -1527,6 +1720,16 @@ public class TimeDetectorStrategyImplTest {
mWakeLockAcquired = false;
}
+ @Override
+ public void addDebugLogEntry(String logMsg) {
+ // No-op for tests
+ }
+
+ @Override
+ public void dumpDebugLog(PrintWriter printWriter) {
+ // No-op for tests
+ }
+
// Methods below are for managing the fake's behavior.
void simulateConfigurationInternalChange(ConfigurationInternal configurationInternal) {
@@ -1538,8 +1741,9 @@ public class TimeDetectorStrategyImplTest {
mElapsedRealtimeMillis = elapsedRealtimeMillis;
}
- void pokeSystemClockMillis(long systemClockMillis) {
+ void pokeSystemClockMillis(long systemClockMillis, @TimeConfidence int timeConfidence) {
mSystemClockMillis = systemClockMillis;
+ mSystemClockConfidence = timeConfidence;
}
long peekElapsedRealtimeMillis() {
@@ -1567,6 +1771,10 @@ public class TimeDetectorStrategyImplTest {
assertEquals(expectedSystemClockMillis, mSystemClockMillis);
}
+ public void verifySystemClockConfidence(@TimeConfidence int expectedConfidence) {
+ assertEquals(expectedConfidence, mSystemClockConfidence);
+ }
+
void resetCallTracking() {
mSystemClockWasSet = false;
}
@@ -1589,6 +1797,14 @@ public class TimeDetectorStrategyImplTest {
mTimeDetectorStrategy = new TimeDetectorStrategyImpl(mFakeEnvironment);
}
+ Script pokeFakeClocks(TimestampedValue<Instant> initialClockTime,
+ @TimeConfidence int timeConfidence) {
+ mFakeEnvironment.pokeElapsedRealtimeMillis(initialClockTime.getReferenceTimeMillis());
+ mFakeEnvironment.pokeSystemClockMillis(
+ initialClockTime.getValue().toEpochMilli(), timeConfidence);
+ return this;
+ }
+
long peekElapsedRealtimeMillis() {
return mFakeEnvironment.peekElapsedRealtimeMillis();
}
@@ -1675,6 +1891,11 @@ public class TimeDetectorStrategyImplTest {
return this;
}
+ Script verifySystemClockConfidence(@TimeConfidence int expectedConfidence) {
+ mFakeEnvironment.verifySystemClockConfidence(expectedConfidence);
+ return this;
+ }
+
/**
* White box test info: Asserts the latest suggestion for the slotIndex is as expected.
*/
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
index 6128428dcb7d..b46e90da3944 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootTaskTests.java
@@ -1312,13 +1312,15 @@ public class RootTaskTests extends WindowTestsBase {
secondActivity.app.setThread(null);
// This should do nothing from a non-attached caller.
assertFalse(task.navigateUpTo(secondActivity /* source record */,
- firstActivity.intent /* destIntent */, null /* destGrants */,
- 0 /* resultCode */, null /* resultData */, null /* resultGrants */));
+ firstActivity.intent /* destIntent */, null /* resolvedType */,
+ null /* destGrants */, 0 /* resultCode */, null /* resultData */,
+ null /* resultGrants */));
secondActivity.app.setThread(thread);
assertTrue(task.navigateUpTo(secondActivity /* source record */,
- firstActivity.intent /* destIntent */, null /* destGrants */,
- 0 /* resultCode */, null /* resultData */, null /* resultGrants */));
+ firstActivity.intent /* destIntent */, null /* resolvedType */,
+ null /* destGrants */, 0 /* resultCode */, null /* resultData */,
+ null /* resultGrants */));
// The firstActivity uses default launch mode, so the activities between it and itself will
// be finished.
assertTrue(secondActivity.finishing);
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 8010a4ae3d56..193c2c143f98 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -1906,30 +1906,6 @@ public class SubscriptionManager {
}
/**
- * @return the count of all subscriptions in the database, this includes
- * all subscriptions that have been seen.
- * @hide
- */
- @UnsupportedAppUsage
- public int getAllSubscriptionInfoCount() {
- if (VDBG) logd("[getAllSubscriptionInfoCount]+");
-
- int result = 0;
-
- try {
- ISub iSub = TelephonyManager.getSubscriptionService();
- if (iSub != null) {
- result = iSub.getAllSubInfoCount(mContext.getOpPackageName(),
- mContext.getAttributionTag());
- }
- } catch (RemoteException ex) {
- // ignore it
- }
-
- return result;
- }
-
- /**
*
* Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* or that the calling app has carrier privileges (see
@@ -2327,12 +2303,6 @@ public class SubscriptionManager {
}
}
- /** @hide */
- @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
- public int getDefaultSmsPhoneId() {
- return getPhoneId(getDefaultSmsSubscriptionId());
- }
-
/**
* Returns the system's default data subscription id.
*
@@ -2381,12 +2351,6 @@ public class SubscriptionManager {
}
/** @hide */
- @UnsupportedAppUsage
- public int getDefaultDataPhoneId() {
- return getPhoneId(getDefaultDataSubscriptionId());
- }
-
- /** @hide */
public void clearSubscriptionInfo() {
try {
ISub iSub = TelephonyManager.getSubscriptionService();
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 1e38b9215d76..917f35bc1b82 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -30,14 +30,6 @@ interface ISub {
List<SubscriptionInfo> getAllSubInfoList(String callingPackage, String callingFeatureId);
/**
- * @param callingPackage The package maing the call.
- * @param callingFeatureId The feature in the package
- * @return the count of all subscriptions in the database, this includes
- * all subscriptions that have been seen.
- */
- int getAllSubInfoCount(String callingPackage, String callingFeatureId);
-
- /**
* Get the active SubscriptionInfo with the subId key
* @param subId The unique SubscriptionInfo key in database
* @param callingPackage The package maing the call.
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
index f77ec8a4a853..8a1e1fabd131 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/BaseTest.kt
@@ -31,46 +31,40 @@ import org.junit.Test
* [ComponentNameMatcher.TASK_BAR], [ComponentNameMatcher.STATUS_BAR], and general assertions
* (layers visible in consecutive states, entire screen covered, etc.)
*/
-abstract class BaseTest @JvmOverloads constructor(
+abstract class BaseTest
+@JvmOverloads
+constructor(
protected val testSpec: FlickerTestParameter,
protected val instrumentation: Instrumentation = InstrumentationRegistry.getInstrumentation(),
protected val tapl: LauncherInstrumentation = LauncherInstrumentation()
) {
init {
testSpec.setIsTablet(
- WindowManagerStateHelper(
- instrumentation,
- clearCacheAfterParsing = false
- ).currentState.wmState.isTablet
+ WindowManagerStateHelper(instrumentation, clearCacheAfterParsing = false)
+ .currentState
+ .wmState
+ .isTablet
)
tapl.setExpectedRotationCheckEnabled(true)
}
- /**
- * Specification of the test transition to execute
- */
+ /** Specification of the test transition to execute */
abstract val transition: FlickerBuilder.() -> Unit
/**
- * Entry point for the test runner. It will use this method to initialize and cache
- * flicker executions
+ * Entry point for the test runner. It will use this method to initialize and cache flicker
+ * executions
*/
@FlickerBuilderProvider
fun buildFlicker(): FlickerBuilder {
return FlickerBuilder(instrumentation).apply {
- setup {
- testSpec.setIsTablet(wmHelper.currentState.wmState.isTablet)
- }
+ setup { testSpec.setIsTablet(wmHelper.currentState.wmState.isTablet) }
transition()
}
}
- /**
- * Checks that all parts of the screen are covered during the transition
- */
- @Presubmit
- @Test
- open fun entireScreenCovered() = testSpec.entireScreenCovered()
+ /** Checks that all parts of the screen are covered during the transition */
+ @Presubmit @Test open fun entireScreenCovered() = testSpec.entireScreenCovered()
/**
* Checks that the [ComponentNameMatcher.NAV_BAR] layer is visible during the whole transition
@@ -110,8 +104,8 @@ abstract class BaseTest @JvmOverloads constructor(
}
/**
- * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible at the start and end of
- * the transition
+ * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible at the start and end of the
+ * transition
*
* Note: Large screen only
*/
@@ -123,8 +117,7 @@ abstract class BaseTest @JvmOverloads constructor(
}
/**
- * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible during the whole
- * transition
+ * Checks that the [ComponentNameMatcher.TASK_BAR] window is visible during the whole transition
*
* Note: Large screen only
*/
@@ -136,8 +129,8 @@ abstract class BaseTest @JvmOverloads constructor(
}
/**
- * Checks that the [ComponentNameMatcher.STATUS_BAR] layer is visible at the start and end
- * of the transition
+ * Checks that the [ComponentNameMatcher.STATUS_BAR] layer is visible at the start and end of
+ * the transition
*/
@Presubmit
@Test
@@ -161,26 +154,22 @@ abstract class BaseTest @JvmOverloads constructor(
open fun statusBarWindowIsAlwaysVisible() = testSpec.statusBarWindowIsAlwaysVisible()
/**
- * Checks that all layers that are visible on the trace, are visible for at least 2
- * consecutive entries.
+ * Checks that all layers that are visible on the trace, are visible for at least 2 consecutive
+ * entries.
*/
@Presubmit
@Test
open fun visibleLayersShownMoreThanOneConsecutiveEntry() {
- testSpec.assertLayers {
- this.visibleLayersShownMoreThanOneConsecutiveEntry()
- }
+ testSpec.assertLayers { this.visibleLayersShownMoreThanOneConsecutiveEntry() }
}
/**
- * Checks that all windows that are visible on the trace, are visible for at least 2
- * consecutive entries.
+ * Checks that all windows that are visible on the trace, are visible for at least 2 consecutive
+ * entries.
*/
@Presubmit
@Test
open fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
- testSpec.assertWm {
- this.visibleWindowsShownMoreThanOneConsecutiveEntry()
- }
+ testSpec.assertWm { this.visibleWindowsShownMoreThanOneConsecutiveEntry() }
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
index c6a7c887c0c7..bbffd0881775 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/CommonAssertions.kt
@@ -15,6 +15,7 @@
*/
@file:JvmName("CommonAssertions")
+
package com.android.server.wm.flicker
import com.android.server.wm.flicker.helpers.WindowUtils
@@ -23,28 +24,24 @@ import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.common.IComponentNameMatcher
/**
- * Checks that [ComponentNameMatcher.STATUS_BAR] window is visible and above the app windows in
- * all WM trace entries
+ * Checks that [ComponentNameMatcher.STATUS_BAR] window is visible and above the app windows in all
+ * WM trace entries
*/
fun FlickerTestParameter.statusBarWindowIsAlwaysVisible() {
- assertWm {
- this.isAboveAppWindowVisible(ComponentNameMatcher.STATUS_BAR)
- }
+ assertWm { this.isAboveAppWindowVisible(ComponentNameMatcher.STATUS_BAR) }
}
/**
- * Checks that [ComponentNameMatcher.NAV_BAR] window is visible and above the app windows in
- * all WM trace entries
+ * Checks that [ComponentNameMatcher.NAV_BAR] window is visible and above the app windows in all WM
+ * trace entries
*/
fun FlickerTestParameter.navBarWindowIsAlwaysVisible() {
- assertWm {
- this.isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR)
- }
+ assertWm { this.isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR) }
}
/**
- * Checks that [ComponentNameMatcher.NAV_BAR] window is visible and above the app windows at the start
- * and end of the WM trace
+ * Checks that [ComponentNameMatcher.NAV_BAR] window is visible and above the app windows at the
+ * start and end of the WM trace
*/
fun FlickerTestParameter.navBarWindowIsVisibleAtStartAndEnd() {
this.navBarWindowIsVisibleAtStart()
@@ -52,51 +49,43 @@ fun FlickerTestParameter.navBarWindowIsVisibleAtStartAndEnd() {
}
/**
- * Checks that [ComponentNameMatcher.NAV_BAR] window is visible and above the app windows at the start
- * of the WM trace
+ * Checks that [ComponentNameMatcher.NAV_BAR] window is visible and above the app windows at the
+ * start of the WM trace
*/
fun FlickerTestParameter.navBarWindowIsVisibleAtStart() {
- assertWmStart {
- this.isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR)
- }
+ assertWmStart { this.isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR) }
}
/**
- * Checks that [ComponentNameMatcher.NAV_BAR] window is visible and above the app windows at the
- * end of the WM trace
+ * Checks that [ComponentNameMatcher.NAV_BAR] window is visible and above the app windows at the end
+ * of the WM trace
*/
fun FlickerTestParameter.navBarWindowIsVisibleAtEnd() {
- assertWmEnd {
- this.isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR)
- }
+ assertWmEnd { this.isAboveAppWindowVisible(ComponentNameMatcher.NAV_BAR) }
}
/**
- * Checks that [ComponentNameMatcher.TASK_BAR] window is visible and above the app windows in
- * all WM trace entries
+ * Checks that [ComponentNameMatcher.TASK_BAR] window is visible and above the app windows in all WM
+ * trace entries
*/
fun FlickerTestParameter.taskBarWindowIsAlwaysVisible() {
- assertWm {
- this.isAboveAppWindowVisible(ComponentNameMatcher.TASK_BAR)
- }
+ assertWm { this.isAboveAppWindowVisible(ComponentNameMatcher.TASK_BAR) }
}
/**
- * Checks that [ComponentNameMatcher.TASK_BAR] window is visible and above the app windows in
- * all WM trace entries
+ * Checks that [ComponentNameMatcher.TASK_BAR] window is visible and above the app windows in all WM
+ * trace entries
*/
fun FlickerTestParameter.taskBarWindowIsVisibleAtEnd() {
- assertWmEnd {
- this.isAboveAppWindowVisible(ComponentNameMatcher.TASK_BAR)
- }
+ assertWmEnd { this.isAboveAppWindowVisible(ComponentNameMatcher.TASK_BAR) }
}
/**
- * If [allStates] is true, checks if the stack space of all displays is fully covered
- * by any visible layer, during the whole transitions
+ * If [allStates] is true, checks if the stack space of all displays is fully covered by any visible
+ * layer, during the whole transitions
*
- * Otherwise, checks if the stack space of all displays is fully covered
- * by any visible layer, at the start and end of the transition
+ * Otherwise, checks if the stack space of all displays is fully covered by any visible layer, at
+ * the start and end of the transition
*
* @param allStates if all states should be checked, othersie, just initial and final
*/
@@ -124,27 +113,18 @@ fun FlickerTestParameter.entireScreenCovered(allStates: Boolean = true) {
}
}
-/**
- * Checks that [ComponentNameMatcher.NAV_BAR] layer is visible at the start of the SF trace
- */
+/** Checks that [ComponentNameMatcher.NAV_BAR] layer is visible at the start of the SF trace */
fun FlickerTestParameter.navBarLayerIsVisibleAtStart() {
- assertLayersStart {
- this.isVisible(ComponentNameMatcher.NAV_BAR)
- }
+ assertLayersStart { this.isVisible(ComponentNameMatcher.NAV_BAR) }
}
-/**
- * Checks that [ComponentNameMatcher.NAV_BAR] layer is visible at the end of the SF trace
- */
+/** Checks that [ComponentNameMatcher.NAV_BAR] layer is visible at the end of the SF trace */
fun FlickerTestParameter.navBarLayerIsVisibleAtEnd() {
- assertLayersEnd {
- this.isVisible(ComponentNameMatcher.NAV_BAR)
- }
+ assertLayersEnd { this.isVisible(ComponentNameMatcher.NAV_BAR) }
}
/**
- * Checks that [ComponentNameMatcher.NAV_BAR] layer is visible at the start and end of the SF
- * trace
+ * Checks that [ComponentNameMatcher.NAV_BAR] layer is visible at the start and end of the SF trace
*/
fun FlickerTestParameter.navBarLayerIsVisibleAtStartAndEnd() {
this.navBarLayerIsVisibleAtStart()
@@ -152,32 +132,21 @@ fun FlickerTestParameter.navBarLayerIsVisibleAtStartAndEnd() {
}
/**
- * Checks that [ComponentNameMatcher.TASK_BAR] layer is visible at the start and end of the SF
- * trace
+ * Checks that [ComponentNameMatcher.TASK_BAR] layer is visible at the start and end of the SF trace
*/
fun FlickerTestParameter.taskBarLayerIsVisibleAtStartAndEnd() {
this.taskBarLayerIsVisibleAtStart()
this.taskBarLayerIsVisibleAtEnd()
}
-/**
- * Checks that [ComponentNameMatcher.TASK_BAR] layer is visible at the start of the SF
- * trace
- */
+/** Checks that [ComponentNameMatcher.TASK_BAR] layer is visible at the start of the SF trace */
fun FlickerTestParameter.taskBarLayerIsVisibleAtStart() {
- assertLayersStart {
- this.isVisible(ComponentNameMatcher.TASK_BAR)
- }
+ assertLayersStart { this.isVisible(ComponentNameMatcher.TASK_BAR) }
}
-/**
- * Checks that [ComponentNameMatcher.TASK_BAR] layer is visible at the end of the SF
- * trace
- */
+/** Checks that [ComponentNameMatcher.TASK_BAR] layer is visible at the end of the SF trace */
fun FlickerTestParameter.taskBarLayerIsVisibleAtEnd() {
- assertLayersEnd {
- this.isVisible(ComponentNameMatcher.TASK_BAR)
- }
+ assertLayersEnd { this.isVisible(ComponentNameMatcher.TASK_BAR) }
}
/**
@@ -185,43 +154,40 @@ fun FlickerTestParameter.taskBarLayerIsVisibleAtEnd() {
* trace
*/
fun FlickerTestParameter.statusBarLayerIsVisibleAtStartAndEnd() {
- assertLayersStart {
- this.isVisible(ComponentNameMatcher.STATUS_BAR)
- }
- assertLayersEnd {
- this.isVisible(ComponentNameMatcher.STATUS_BAR)
- }
+ assertLayersStart { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
+ assertLayersEnd { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
}
/**
- * Asserts that the [ComponentNameMatcher.NAV_BAR] layer is at the correct position at the start
- * of the SF trace
+ * Asserts that the [ComponentNameMatcher.NAV_BAR] layer is at the correct position at the start of
+ * the SF trace
*/
fun FlickerTestParameter.navBarLayerPositionAtStart() {
assertLayersStart {
- val display = this.entry.displays.firstOrNull { !it.isVirtual }
- ?: error("There is no display!")
+ val display =
+ this.entry.displays.firstOrNull { !it.isVirtual } ?: error("There is no display!")
this.visibleRegion(ComponentNameMatcher.NAV_BAR)
.coversExactly(WindowUtils.getNavigationBarPosition(display, isGesturalNavigation))
}
}
/**
- * Asserts that the [ComponentNameMatcher.NAV_BAR] layer is at the correct position at the end
- * of the SF trace
+ * Asserts that the [ComponentNameMatcher.NAV_BAR] layer is at the correct position at the end of
+ * the SF trace
*/
fun FlickerTestParameter.navBarLayerPositionAtEnd() {
assertLayersEnd {
- val display = this.entry.displays.minByOrNull { it.id }
- ?: throw RuntimeException("There is no display!")
+ val display =
+ this.entry.displays.minByOrNull { it.id }
+ ?: throw RuntimeException("There is no display!")
this.visibleRegion(ComponentNameMatcher.NAV_BAR)
.coversExactly(WindowUtils.getNavigationBarPosition(display, isGesturalNavigation))
}
}
/**
- * Asserts that the [ComponentNameMatcher.NAV_BAR] layer is at the correct position at the start
- * and end of the SF trace
+ * Asserts that the [ComponentNameMatcher.NAV_BAR] layer is at the correct position at the start and
+ * end of the SF trace
*/
fun FlickerTestParameter.navBarLayerPositionAtStartAndEnd() {
navBarLayerPositionAtStart()
@@ -234,21 +200,23 @@ fun FlickerTestParameter.navBarLayerPositionAtStartAndEnd() {
*/
fun FlickerTestParameter.statusBarLayerPositionAtStart() {
assertLayersStart {
- val display = this.entry.displays.minByOrNull { it.id }
- ?: throw RuntimeException("There is no display!")
+ val display =
+ this.entry.displays.minByOrNull { it.id }
+ ?: throw RuntimeException("There is no display!")
this.visibleRegion(ComponentNameMatcher.STATUS_BAR)
.coversExactly(WindowUtils.getStatusBarPosition(display))
}
}
/**
- * Asserts that the [ComponentNameMatcher.STATUS_BAR] layer is at the correct position at the end
- * of the SF trace
+ * Asserts that the [ComponentNameMatcher.STATUS_BAR] layer is at the correct position at the end of
+ * the SF trace
*/
fun FlickerTestParameter.statusBarLayerPositionAtEnd() {
assertLayersEnd {
- val display = this.entry.displays.minByOrNull { it.id }
- ?: throw RuntimeException("There is no display!")
+ val display =
+ this.entry.displays.minByOrNull { it.id }
+ ?: throw RuntimeException("There is no display!")
this.visibleRegion(ComponentNameMatcher.STATUS_BAR)
.coversExactly(WindowUtils.getStatusBarPosition(display))
}
@@ -264,23 +232,25 @@ fun FlickerTestParameter.statusBarLayerPositionAtStartAndEnd() {
}
/**
- * Asserts that the visibleRegion of the [ComponentNameMatcher.SNAPSHOT] layer can cover
- * the visibleRegion of the given app component exactly
+ * Asserts that the visibleRegion of the [ComponentNameMatcher.SNAPSHOT] layer can cover the
+ * visibleRegion of the given app component exactly
*/
fun FlickerTestParameter.snapshotStartingWindowLayerCoversExactlyOnApp(
component: IComponentNameMatcher
) {
assertLayers {
invoke("snapshotStartingWindowLayerCoversExactlyOnApp") {
- val snapshotLayers = it.subjects.filter { subject ->
- subject.name.contains(
- ComponentNameMatcher.SNAPSHOT.toLayerName()) && subject.isVisible
- }
+ val snapshotLayers =
+ it.subjects.filter { subject ->
+ subject.name.contains(ComponentNameMatcher.SNAPSHOT.toLayerName()) &&
+ subject.isVisible
+ }
// Verify the size of snapshotRegion covers appVisibleRegion exactly in animation.
if (snapshotLayers.isNotEmpty()) {
- val visibleAreas = snapshotLayers.mapNotNull { snapshotLayer ->
- snapshotLayer.layer?.visibleRegion
- }.toTypedArray()
+ val visibleAreas =
+ snapshotLayers
+ .mapNotNull { snapshotLayer -> snapshotLayer.layer?.visibleRegion }
+ .toTypedArray()
val snapshotRegion = RegionSubject.assertThat(visibleAreas, this, timestamp)
val appVisibleRegion = it.visibleRegion(component)
if (snapshotRegion.region.isNotEmpty) {
@@ -293,22 +263,33 @@ fun FlickerTestParameter.snapshotStartingWindowLayerCoversExactlyOnApp(
/**
* Asserts that:
+ * ```
* [originalLayer] is visible at the start of the trace
* [originalLayer] becomes invisible during the trace and (in the same entry) [newLayer]
* becomes visible
* [newLayer] remains visible until the end of the trace
*
- * @param originalLayer Layer that should be visible at the start
+ * @param originalLayer
+ * ```
+ * Layer that should be visible at the start
* @param newLayer Layer that should be visible at the end
* @param ignoreEntriesWithRotationLayer If entries with a visible rotation layer should be ignored
+ * ```
* when checking the transition. If true we will not fail the assertion if a rotation layer is
* visible to fill the gap between the [originalLayer] being visible and the [newLayer] being
* visible.
- * @param ignoreSnapshot If the snapshot layer should be ignored during the transition
+ * @param ignoreSnapshot
+ * ```
+ * If the snapshot layer should be ignored during the transition
+ * ```
* (useful mostly for app launch)
- * @param ignoreSplashscreen If the splashscreen layer should be ignored during the transition.
+ * @param ignoreSplashscreen
+ * ```
+ * If the splashscreen layer should be ignored during the transition.
+ * ```
* If true then we will allow for a splashscreen to be shown before the layer is shown,
* otherwise we won't and the layer must appear immediately.
+ * ```
*/
fun FlickerTestParameter.replacesLayer(
originalLayer: IComponentNameMatcher,
@@ -333,13 +314,7 @@ fun FlickerTestParameter.replacesLayer(
assertion.then().isVisible(newLayer)
}
- assertLayersStart {
- this.isVisible(originalLayer)
- .isInvisible(newLayer)
- }
+ assertLayersStart { this.isVisible(originalLayer).isInvisible(newLayer) }
- assertLayersEnd {
- this.isInvisible(originalLayer)
- .isVisible(newLayer)
- }
+ assertLayersEnd { this.isInvisible(originalLayer).isVisible(newLayer) }
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplit.kt
index 79654e36a888..b23fb5a284c1 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/OpenActivityEmbeddingPlaceholderSplit.kt
@@ -41,9 +41,8 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenActivityEmbeddingPlaceholderSplit(
- testSpec: FlickerTestParameter
-) : ActivityEmbeddingTestBase(testSpec) {
+class OpenActivityEmbeddingPlaceholderSplit(testSpec: FlickerTestParameter) :
+ ActivityEmbeddingTestBase(testSpec) {
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit = {
@@ -51,9 +50,7 @@ class OpenActivityEmbeddingPlaceholderSplit(
tapl.setExpectedRotationCheckEnabled(false)
testApp.launchViaIntent(wmHelper)
}
- transitions {
- testApp.launchPlaceholderSplit(wmHelper)
- }
+ transitions { testApp.launchPlaceholderSplit(wmHelper) }
teardown {
tapl.goHome()
testApp.exit(wmHelper)
@@ -65,8 +62,8 @@ class OpenActivityEmbeddingPlaceholderSplit(
fun mainActivityBecomesInvisible() {
testSpec.assertLayers {
isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
- .then()
- .isInvisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+ .then()
+ .isInvisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
}
}
@@ -75,20 +72,18 @@ class OpenActivityEmbeddingPlaceholderSplit(
fun placeholderSplitBecomesVisible() {
testSpec.assertLayers {
isInvisible(ActivityEmbeddingAppHelper.PLACEHOLDER_PRIMARY_COMPONENT)
- .then()
- .isVisible(ActivityEmbeddingAppHelper.PLACEHOLDER_PRIMARY_COMPONENT)
+ .then()
+ .isVisible(ActivityEmbeddingAppHelper.PLACEHOLDER_PRIMARY_COMPONENT)
}
testSpec.assertLayers {
isInvisible(ActivityEmbeddingAppHelper.PLACEHOLDER_SECONDARY_COMPONENT)
- .then()
- .isVisible(ActivityEmbeddingAppHelper.PLACEHOLDER_SECONDARY_COMPONENT)
+ .then()
+ .isVisible(ActivityEmbeddingAppHelper.PLACEHOLDER_SECONDARY_COMPONENT)
}
}
/** {@inheritDoc} */
- @Presubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
+ @Presubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
/** {@inheritDoc} */
@Presubmit
@@ -124,14 +119,12 @@ class OpenActivityEmbeddingPlaceholderSplit(
/** {@inheritDoc} */
@Presubmit
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
@Presubmit
@Test
- override fun statusBarWindowIsAlwaysVisible() =
- super.statusBarWindowIsAlwaysVisible()
+ override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
@Presubmit
@@ -149,20 +142,21 @@ class OpenActivityEmbeddingPlaceholderSplit(
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(
- supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90),
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- )
- )
+ .getConfigNonRotationTests(
+ supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90),
+ supportedNavigationModes =
+ listOf(
+ WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
+ WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
+ )
+ )
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
index 8fdd37d3777c..b16bfe070374 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppBackButtonTest.kt
@@ -1,4 +1,3 @@
-
/*
* Copyright (C) 2020 The Android Open Source Project
*
@@ -36,28 +35,34 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:CloseAppBackButtonTest`
*
* Actions:
+ * ```
* Make sure no apps are running on the device
* Launch an app [testApp] and wait animation to complete
* Press back button
- *
+ * ```
* To run only the presubmit assertions add: `--
+ * ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
- *
+ * ```
* To run only the postsubmit assertions add: `--
+ * ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
- *
+ * ```
* To run only the flaky assertions add: `--
+ * ```
* --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [CloseAppTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@FlickerServiceCompatible
@@ -71,9 +76,7 @@ class CloseAppBackButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio
super.transition(this)
transitions {
tapl.pressBack()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
}
}
@@ -86,14 +89,13 @@ class CloseAppBackButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): List<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
index 765be20ea1bd..78d0860f2636 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppHomeButtonTest.kt
@@ -35,28 +35,34 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:CloseAppHomeButtonTest`
*
* Actions:
+ * ```
* Make sure no apps are running on the device
* Launch an app [testApp] and wait animation to complete
* Press home button
- *
+ * ```
* To run only the presubmit assertions add: `--
+ * ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
- *
+ * ```
* To run only the postsubmit assertions add: `--
+ * ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
- *
+ * ```
* To run only the flaky assertions add: `--
+ * ```
* --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [CloseAppTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@FlickerServiceCompatible
@@ -68,18 +74,14 @@ class CloseAppHomeButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
- setup {
- tapl.setExpectedRotationCheckEnabled(false)
- }
+ setup { tapl.setExpectedRotationCheckEnabled(false) }
transitions {
// Can't use TAPL at the moment because of rotation test issues
// When pressing home, TAPL expects the orientation to remain constant
// However, when closing a landscape app back to a portrait-only launcher
// this causes an error in verifyActiveContainer();
tapl.goHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
}
}
@@ -92,14 +94,13 @@ class CloseAppHomeButtonTest(testSpec: FlickerTestParameter) : CloseAppTransitio
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
index f296d9746aef..5bb227f36333 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/close/CloseAppTransition.kt
@@ -27,9 +27,7 @@ import com.android.server.wm.flicker.replacesLayer
import com.android.server.wm.traces.common.ComponentNameMatcher.Companion.LAUNCHER
import org.junit.Test
-/**
- * Base test class for transitions that close an app back to the launcher screen
- */
+/** Base test class for transitions that close an app back to the launcher screen */
abstract class CloseAppTransition(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
protected open val testApp: StandardAppHelper = SimpleAppHelper(instrumentation)
@@ -40,42 +38,30 @@ abstract class CloseAppTransition(testSpec: FlickerTestParameter) : BaseTest(tes
testApp.launchViaIntent(wmHelper)
this.setRotation(testSpec.startRotation)
}
- teardown {
- testApp.exit(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
}
/**
- * Checks that [testApp] is the top visible app window at the start of the transition and
- * that it is replaced by [LAUNCHER] during the transition
+ * Checks that [testApp] is the top visible app window at the start of the transition and that
+ * it is replaced by [LAUNCHER] during the transition
*/
@Presubmit
@Test
open fun launcherReplacesAppWindowAsTopWindow() {
- testSpec.assertWm {
- this.isAppWindowOnTop(testApp)
- .then()
- .isAppWindowOnTop(LAUNCHER)
- }
+ testSpec.assertWm { this.isAppWindowOnTop(testApp).then().isAppWindowOnTop(LAUNCHER) }
}
/**
- * Checks that [LAUNCHER] is invisible at the start of the transition and that
- * it becomes visible during the transition
+ * Checks that [LAUNCHER] is invisible at the start of the transition and that it becomes
+ * visible during the transition
*/
@Presubmit
@Test
open fun launcherWindowBecomesVisible() {
- testSpec.assertWm {
- this.isAppWindowNotOnTop(LAUNCHER)
- .then()
- .isAppWindowOnTop(LAUNCHER)
- }
+ testSpec.assertWm { this.isAppWindowNotOnTop(LAUNCHER).then().isAppWindowOnTop(LAUNCHER) }
}
- /**
- * Checks that [LAUNCHER] layer becomes visible when [testApp] becomes invisible
- */
+ /** Checks that [LAUNCHER] layer becomes visible when [testApp] becomes invisible */
@Presubmit
@Test
open fun launcherLayerReplacesApp() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
index ef5cec29f898..48e1e64a05eb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt
@@ -32,13 +32,14 @@ import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import org.junit.Assume.assumeNotNull
-class ActivityEmbeddingAppHelper @JvmOverloads constructor(
+class ActivityEmbeddingAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.ActivityEmbedding.MainActivity.LABEL,
component: ComponentNameMatcher = MAIN_ACTIVITY_COMPONENT,
- launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
- .getInstance(instr)
- .launcherStrategy
+ launcherStrategy: ILauncherStrategy =
+ LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
/**
@@ -46,14 +47,15 @@ class ActivityEmbeddingAppHelper @JvmOverloads constructor(
* placeholder secondary activity based on the placeholder rule.
*/
fun launchPlaceholderSplit(wmHelper: WindowManagerStateHelper) {
- val launchButton = uiDevice.wait(
- Until.findObject(By.res(getPackage(), "launch_placeholder_split_button")),
- FIND_TIMEOUT)
- require(launchButton != null) {
- "Can't find launch placeholder split button on screen."
- }
+ val launchButton =
+ uiDevice.wait(
+ Until.findObject(By.res(getPackage(), "launch_placeholder_split_button")),
+ FIND_TIMEOUT
+ )
+ require(launchButton != null) { "Can't find launch placeholder split button on screen." }
launchButton.click()
- wmHelper.StateSyncBuilder()
+ wmHelper
+ .StateSyncBuilder()
.withActivityState(PLACEHOLDER_PRIMARY_COMPONENT, STATE_RESUMED)
.withActivityState(PLACEHOLDER_SECONDARY_COMPONENT, STATE_RESUMED)
.waitForAndVerify()
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt
index 34f9ce43b4bc..a2d4d3a01a4a 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/CameraAppHelper.kt
@@ -23,12 +23,18 @@ import android.content.pm.ResolveInfo
import android.provider.MediaStore
import com.android.server.wm.traces.common.ComponentNameMatcher
-class CameraAppHelper @JvmOverloads constructor(
+class CameraAppHelper
+@JvmOverloads
+constructor(
instrumentation: Instrumentation,
pkgManager: PackageManager = instrumentation.context.packageManager
-) : StandardAppHelper(instrumentation, getCameraLauncherName(pkgManager),
- getCameraComponent(pkgManager)){
- companion object{
+) :
+ StandardAppHelper(
+ instrumentation,
+ getCameraLauncherName(pkgManager),
+ getCameraComponent(pkgManager)
+ ) {
+ companion object {
private fun getCameraIntent(): Intent {
return Intent(MediaStore.ACTION_IMAGE_CAPTURE)
}
@@ -36,13 +42,15 @@ class CameraAppHelper @JvmOverloads constructor(
private fun getResolveInfo(pkgManager: PackageManager): ResolveInfo {
val intent = getCameraIntent()
return pkgManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY)
- ?: error("unable to resolve camera activity")
+ ?: error("unable to resolve camera activity")
}
private fun getCameraComponent(pkgManager: PackageManager): ComponentNameMatcher {
val resolveInfo = getResolveInfo(pkgManager)
- return ComponentNameMatcher(resolveInfo.activityInfo.packageName,
- className = resolveInfo.activityInfo.name)
+ return ComponentNameMatcher(
+ resolveInfo.activityInfo.packageName,
+ className = resolveInfo.activityInfo.name
+ )
}
private fun getCameraLauncherName(pkgManager: PackageManager): String {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
index 132e7b6fef6d..4340bd788046 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FixedOrientationAppHelper.kt
@@ -23,12 +23,13 @@ import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
-class FixedOrientationAppHelper @JvmOverloads constructor(
+class FixedOrientationAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.PortraitOnlyActivity.LABEL,
component: ComponentNameMatcher =
ActivityOptions.PortraitOnlyActivity.COMPONENT.toFlickerComponent(),
- launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
- .getInstance(instr)
- .launcherStrategy
+ launcherStrategy: ILauncherStrategy =
+ LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
index d08cb5525d5e..73cb8627a068 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/FlickerExtensions.kt
@@ -15,6 +15,7 @@
*/
@file:JvmName("FlickerExtensions")
+
package com.android.server.wm.flicker.helpers
import com.android.server.wm.flicker.Flicker
@@ -31,4 +32,4 @@ fun Flicker.setRotation(rotation: Int) =
instrumentation,
clearCacheAfterParsing = false,
wmHelper = wmHelper
-)
+ )
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
index 2d81e0d9e165..d45315e68e37 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt
@@ -27,7 +27,9 @@ import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
-class GameAppHelper @JvmOverloads constructor(
+class GameAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.Game.LABEL,
component: ComponentNameMatcher = ActivityOptions.Game.COMPONENT.toFlickerComponent(),
@@ -41,13 +43,18 @@ class GameAppHelper @JvmOverloads constructor(
* @return true if the swipe operation is successful.
*/
fun swipeDown(): Boolean {
- val gameView = uiDevice.wait(
- Until.findObject(By.res(getPackage(), GAME_APP_VIEW_RES)), WAIT_TIME_MS)
+ val gameView =
+ uiDevice.wait(Until.findObject(By.res(getPackage(), GAME_APP_VIEW_RES)), WAIT_TIME_MS)
require(gameView != null) { "Mock game app view not found." }
val bound = gameView.getVisibleBounds()
return uiDevice.swipe(
- bound.centerX(), bound.top, bound.centerX(), bound.centerY(), SWIPE_STEPS)
+ bound.centerX(),
+ bound.top,
+ bound.centerX(),
+ bound.centerY(),
+ SWIPE_STEPS
+ )
}
/**
@@ -63,21 +70,27 @@ class GameAppHelper @JvmOverloads constructor(
wmHelper: WindowManagerStateHelper,
direction: Direction
): Boolean {
- val ratioForScreenBottom = 0.97
+ val ratioForScreenBottom = 0.99
val fullView = wmHelper.getWindowRegion(componentMatcher)
require(!fullView.isEmpty) { "Target $componentMatcher view not found." }
val bound = fullView.bounds
val targetYPos = bound.bottom * ratioForScreenBottom
- val endX = when (direction) {
- Direction.LEFT -> bound.left
- Direction.RIGHT -> bound.right
- else -> {
- throw IllegalStateException("Only left or right direction is allowed.")
+ val endX =
+ when (direction) {
+ Direction.LEFT -> bound.left
+ Direction.RIGHT -> bound.right
+ else -> {
+ throw IllegalStateException("Only left or right direction is allowed.")
+ }
}
- }
return uiDevice.swipe(
- bound.centerX(), targetYPos.toInt(), endX, targetYPos.toInt(), SWIPE_STEPS)
+ bound.centerX(),
+ targetYPos.toInt(),
+ endX,
+ targetYPos.toInt(),
+ SWIPE_STEPS
+ )
}
/**
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt
index b5b0da934ad9..16753e63eb01 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppAutoFocusHelper.kt
@@ -28,7 +28,9 @@ import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
import java.util.regex.Pattern
-class ImeAppAutoFocusHelper @JvmOverloads constructor(
+class ImeAppAutoFocusHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
private val rotation: Int,
private val imePackageName: String = IME_PACKAGE,
@@ -52,59 +54,61 @@ class ImeAppAutoFocusHelper @JvmOverloads constructor(
}
override fun open() {
- val expectedPackage = if (rotation.isRotated()) {
- imePackageName
- } else {
- getPackage()
- }
+ val expectedPackage =
+ if (rotation.isRotated()) {
+ imePackageName
+ } else {
+ getPackage()
+ }
launcherStrategy.launch(appName, expectedPackage)
}
fun startDialogThemedActivity(wmHelper: WindowManagerStateHelper) {
- val button = uiDevice.wait(Until.findObject(By.res(getPackage(),
- "start_dialog_themed_activity_btn")), FIND_TIMEOUT)
+ val button =
+ uiDevice.wait(
+ Until.findObject(By.res(getPackage(), "start_dialog_themed_activity_btn")),
+ FIND_TIMEOUT
+ )
requireNotNull(button) {
"Button not found, this usually happens when the device " +
"was left in an unknown state (e.g. Screen turned off)"
}
button.click()
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(
- ActivityOptions.DialogThemedActivity.COMPONENT.toFlickerComponent())
+ wmHelper
+ .StateSyncBuilder()
+ .withFullScreenApp(ActivityOptions.DialogThemedActivity.COMPONENT.toFlickerComponent())
.waitForAndVerify()
}
fun dismissDialog(wmHelper: WindowManagerStateHelper) {
- val dialog = uiDevice.wait(
- Until.findObject(By.text("Dialog for test")), FIND_TIMEOUT)
+ val dialog = uiDevice.wait(Until.findObject(By.text("Dialog for test")), FIND_TIMEOUT)
// Pressing back key to dismiss the dialog
if (dialog != null) {
uiDevice.pressBack()
- wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
}
}
fun getInsetsVisibleFromDialog(type: Int): Boolean {
- val insetsVisibilityTextView = uiDevice.wait(
- Until.findObject(By.res("android:id/text1")), FIND_TIMEOUT)
+ val insetsVisibilityTextView =
+ uiDevice.wait(Until.findObject(By.res("android:id/text1")), FIND_TIMEOUT)
if (insetsVisibilityTextView != null) {
val visibility = insetsVisibilityTextView.text.toString()
- val matcher = when (type) {
- ime() -> {
- Pattern.compile("IME\\: (VISIBLE|INVISIBLE)").matcher(visibility)
- }
- statusBars() -> {
- Pattern.compile("StatusBar\\: (VISIBLE|INVISIBLE)").matcher(visibility)
+ val matcher =
+ when (type) {
+ ime() -> {
+ Pattern.compile("IME\\: (VISIBLE|INVISIBLE)").matcher(visibility)
+ }
+ statusBars() -> {
+ Pattern.compile("StatusBar\\: (VISIBLE|INVISIBLE)").matcher(visibility)
+ }
+ navigationBars() -> {
+ Pattern.compile("NavBar\\: (VISIBLE|INVISIBLE)").matcher(visibility)
+ }
+ else -> null
}
- navigationBars() -> {
- Pattern.compile("NavBar\\: (VISIBLE|INVISIBLE)").matcher(visibility)
- }
- else -> null
- }
if (matcher != null && matcher.find()) {
return matcher.group(1).equals("VISIBLE")
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
index 56b6b92dd6ef..cefbf18d33c9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeAppHelper.kt
@@ -26,11 +26,12 @@ import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
-open class ImeAppHelper @JvmOverloads constructor(
+open class ImeAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.Ime.Default.LABEL,
- component: ComponentNameMatcher =
- ActivityOptions.Ime.Default.COMPONENT.toFlickerComponent(),
+ component: ComponentNameMatcher = ActivityOptions.Ime.Default.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy =
LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
@@ -40,9 +41,8 @@ open class ImeAppHelper @JvmOverloads constructor(
* @param wmHelper Helper used to wait for WindowManager states
*/
open fun openIME(wmHelper: WindowManagerStateHelper) {
- val editText = uiDevice.wait(
- Until.findObject(By.res(getPackage(), "plain_text_input")),
- FIND_TIMEOUT)
+ val editText =
+ uiDevice.wait(Until.findObject(By.res(getPackage(), "plain_text_input")), FIND_TIMEOUT)
requireNotNull(editText) {
"Text field not found, this usually happens when the device " +
@@ -53,9 +53,7 @@ open class ImeAppHelper @JvmOverloads constructor(
}
protected fun waitIMEShown(wmHelper: WindowManagerStateHelper) {
- wmHelper.StateSyncBuilder()
- .withImeShown()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withImeShown().waitForAndVerify()
}
/**
@@ -65,21 +63,19 @@ open class ImeAppHelper @JvmOverloads constructor(
*/
open fun closeIME(wmHelper: WindowManagerStateHelper) {
uiDevice.pressBack()
- wmHelper.StateSyncBuilder()
- .withImeGone()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withImeGone().waitForAndVerify()
}
open fun finishActivity(wmHelper: WindowManagerStateHelper) {
- val finishButton = uiDevice.wait(
- Until.findObject(By.res(getPackage(), "finish_activity_btn")),
- FIND_TIMEOUT)
+ val finishButton =
+ uiDevice.wait(
+ Until.findObject(By.res(getPackage(), "finish_activity_btn")),
+ FIND_TIMEOUT
+ )
requireNotNull(finishButton) {
"Finish activity button not found, probably IME activity is not on the screen?"
}
finishButton.click()
- wmHelper.StateSyncBuilder()
- .withActivityRemoved(this)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withActivityRemoved(this).waitForAndVerify()
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
index bfb68da20836..871b66ecbf0e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeEditorPopupDialogAppHelper.kt
@@ -24,7 +24,9 @@ import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
-class ImeEditorPopupDialogAppHelper @JvmOverloads constructor(
+class ImeEditorPopupDialogAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.Ime.EditorPopupDialogActivity.LABEL,
component: ComponentNameMatcher =
@@ -42,15 +44,12 @@ class ImeEditorPopupDialogAppHelper @JvmOverloads constructor(
}
fun dismissDialog(wmHelper: WindowManagerStateHelper) {
- val dismissButton = uiDevice.wait(
- Until.findObject(By.text("Dismiss")), FIND_TIMEOUT)
+ val dismissButton = uiDevice.wait(Until.findObject(By.text("Dismiss")), FIND_TIMEOUT)
// Pressing back key to dismiss the dialog
if (dismissButton != null) {
dismissButton.click()
- wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
index 3b8d3c3440a8..1502ad5cde58 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ImeStateInitializeHelper.kt
@@ -23,7 +23,9 @@ import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
-class ImeStateInitializeHelper @JvmOverloads constructor(
+class ImeStateInitializeHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.Ime.StateInitializeActivity.LABEL,
component: ComponentNameMatcher =
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt
index cb54b5732c8d..ba8dabd4dfec 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/LaunchBubbleHelper.kt
@@ -20,8 +20,9 @@ import android.app.Instrumentation
import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.parser.toFlickerComponent
-class LaunchBubbleHelper(instrumentation: Instrumentation) : StandardAppHelper(
- instrumentation,
- ActivityOptions.Bubbles.LaunchBubble.LABEL,
- ActivityOptions.Bubbles.LaunchBubble.COMPONENT.toFlickerComponent()
-)
+class LaunchBubbleHelper(instrumentation: Instrumentation) :
+ StandardAppHelper(
+ instrumentation,
+ ActivityOptions.Bubbles.LaunchBubble.LABEL,
+ ActivityOptions.Bubbles.LaunchBubble.COMPONENT.toFlickerComponent()
+ )
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
index dde0b3e6873d..f00904bd7570 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt
@@ -27,19 +27,19 @@ import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
-class MailAppHelper @JvmOverloads constructor(
+class MailAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.Mail.LABEL,
- component: ComponentNameMatcher =
- ActivityOptions.Mail.COMPONENT.toFlickerComponent(),
- launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
- .getInstance(instr)
- .launcherStrategy
+ component: ComponentNameMatcher = ActivityOptions.Mail.COMPONENT.toFlickerComponent(),
+ launcherStrategy: ILauncherStrategy =
+ LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
fun openMail(rowIdx: Int) {
- val rowSel = By.res(getPackage(), "mail_row_item_text")
- .textEndsWith(String.format("%04d", rowIdx))
+ val rowSel =
+ By.res(getPackage(), "mail_row_item_text").textEndsWith(String.format("%04d", rowIdx))
var row: UiObject2? = null
for (i in 1..1000) {
row = uiDevice.wait(Until.findObject(rowSel), SHORT_WAIT_TIME_MS)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
index 9bdfadb35ff3..e0f6fb0a5bbc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MultiWindowUtils.kt
@@ -40,23 +40,29 @@ class MultiWindowUtils(
}
fun getDevEnableNonResizableMultiWindow(context: Context): Int =
- Settings.Global.getInt(context.contentResolver,
- Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW)
+ Settings.Global.getInt(
+ context.contentResolver,
+ Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW
+ )
fun setDevEnableNonResizableMultiWindow(context: Context, configValue: Int) =
- Settings.Global.putInt(context.contentResolver,
- Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW, configValue)
+ Settings.Global.putInt(
+ context.contentResolver,
+ Settings.Global.DEVELOPMENT_ENABLE_NON_RESIZABLE_MULTI_WINDOW,
+ configValue
+ )
fun setSupportsNonResizableMultiWindow(instrumentation: Instrumentation, configValue: Int) =
executeShellCommand(
- instrumentation,
- createConfigSupportsNonResizableMultiWindowCommand(configValue))
+ instrumentation,
+ createConfigSupportsNonResizableMultiWindowCommand(configValue)
+ )
fun resetMultiWindowConfig(instrumentation: Instrumentation) =
executeShellCommand(instrumentation, resetMultiWindowConfigCommand)
private fun createConfigSupportsNonResizableMultiWindowCommand(configValue: Int): String =
- "wm set-multi-window-config --supportsNonResizable $configValue"
+ "wm set-multi-window-config --supportsNonResizable $configValue"
private const val resetMultiWindowConfigCommand: String = "wm reset-multi-window-config"
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
index f3386afa610c..34294a6b7304 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NewTasksAppHelper.kt
@@ -27,27 +27,24 @@ import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
-class NewTasksAppHelper @JvmOverloads constructor(
+class NewTasksAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.LaunchNewTask.LABEL,
- component: ComponentNameMatcher =
- ActivityOptions.LaunchNewTask.COMPONENT.toFlickerComponent(),
- launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
- .getInstance(instr)
- .launcherStrategy
+ component: ComponentNameMatcher = ActivityOptions.LaunchNewTask.COMPONENT.toFlickerComponent(),
+ launcherStrategy: ILauncherStrategy =
+ LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
fun openNewTask(device: UiDevice, wmHelper: WindowManagerStateHelper) {
- val button = device.wait(
- Until.findObject(By.res(getPackage(), "launch_new_task")),
- FIND_TIMEOUT)
+ val button =
+ device.wait(Until.findObject(By.res(getPackage(), "launch_new_task")), FIND_TIMEOUT)
requireNotNull(button) {
"Button not found, this usually happens when the device " +
"was left in an unknown state (e.g. in split screen)"
}
button.click()
- wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
index 19ce3ba21812..bbb782d7ae50 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NonResizeableAppHelper.kt
@@ -23,7 +23,9 @@ import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
-class NonResizeableAppHelper @JvmOverloads constructor(
+class NonResizeableAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.NonResizeableActivity.LABEL,
component: ComponentNameMatcher =
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
index 97642f1617af..a3e32e501ce2 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/NotificationAppHelper.kt
@@ -26,19 +26,18 @@ import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
-class NotificationAppHelper @JvmOverloads constructor(
+class NotificationAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.Notification.LABEL,
- component: ComponentNameMatcher =
- ActivityOptions.Notification.COMPONENT.toFlickerComponent(),
- launcherStrategy: ILauncherStrategy = LauncherStrategyFactory
- .getInstance(instr)
- .launcherStrategy
+ component: ComponentNameMatcher = ActivityOptions.Notification.COMPONENT.toFlickerComponent(),
+ launcherStrategy: ILauncherStrategy =
+ LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy) {
fun postNotification(wmHelper: WindowManagerStateHelper) {
- val button = uiDevice.wait(
- Until.findObject(By.res(getPackage(), "post_notification")),
- FIND_TIMEOUT)
+ val button =
+ uiDevice.wait(Until.findObject(By.res(getPackage(), "post_notification")), FIND_TIMEOUT)
requireNotNull(button) {
"Post notification button not found, this usually happens when the device " +
@@ -48,8 +47,6 @@ class NotificationAppHelper @JvmOverloads constructor(
uiDevice.wait(Until.findObject(By.text("Flicker Test Notification")), FIND_TIMEOUT)
?: error("Flicker Notification not found")
- wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
index dc49fc8021d9..e730f315392b 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/PipAppHelper.kt
@@ -29,19 +29,20 @@ import com.android.server.wm.traces.common.region.Region
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
-open class PipAppHelper(instrumentation: Instrumentation) : StandardAppHelper(
- instrumentation,
- ActivityOptions.Pip.LABEL,
- ActivityOptions.Pip.COMPONENT.toFlickerComponent()
-) {
+open class PipAppHelper(instrumentation: Instrumentation) :
+ StandardAppHelper(
+ instrumentation,
+ ActivityOptions.Pip.LABEL,
+ ActivityOptions.Pip.COMPONENT.toFlickerComponent()
+ ) {
private val mediaSessionManager: MediaSessionManager
- get() = context.getSystemService(MediaSessionManager::class.java)
- ?: error("Could not get MediaSessionManager")
+ get() =
+ context.getSystemService(MediaSessionManager::class.java)
+ ?: error("Could not get MediaSessionManager")
private val mediaController: MediaController?
- get() = mediaSessionManager.getActiveSessions(null).firstOrNull {
- it.packageName == `package`
- }
+ get() =
+ mediaSessionManager.getActiveSessions(null).firstOrNull { it.packageName == `package` }
open fun clickObject(resId: String) {
val selector = By.res(`package`, resId)
@@ -51,8 +52,8 @@ open class PipAppHelper(instrumentation: Instrumentation) : StandardAppHelper(
}
/**
- * Launches the app through an intent instead of interacting with the launcher and waits
- * until the app window is in PIP mode
+ * Launches the app through an intent instead of interacting with the launcher and waits until
+ * the app window is in PIP mode
*/
@JvmOverloads
fun launchViaIntentAndWaitForPip(
@@ -62,18 +63,17 @@ open class PipAppHelper(instrumentation: Instrumentation) : StandardAppHelper(
stringExtras: Map<String, String>
) {
launchViaIntentAndWaitShown(
- wmHelper, expectedWindowName, action, stringExtras,
+ wmHelper,
+ expectedWindowName,
+ action,
+ stringExtras,
waitConditions = arrayOf(WindowManagerConditionsFactory.hasPipWindow())
)
- wmHelper.StateSyncBuilder()
- .withPipShown()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withPipShown().waitForAndVerify()
}
- /**
- * Expand the PIP window back to full screen via intent and wait until the app is visible
- */
+ /** Expand the PIP window back to full screen via intent and wait until the app is visible */
fun exitPipToFullScreenViaIntent(wmHelper: WindowManagerStateHelper) =
launchViaIntentAndWaitShown(wmHelper)
@@ -81,9 +81,7 @@ open class PipAppHelper(instrumentation: Instrumentation) : StandardAppHelper(
clickObject(ENTER_PIP_BUTTON_ID)
// Wait on WMHelper or simply wait for 3 seconds
- wmHelper.StateSyncBuilder()
- .withPipShown()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withPipShown().waitForAndVerify()
// when entering pip, the dismiss button is visible at the start. to ensure the pip
// animation is complete, wait until the pip dismiss button is no longer visible.
// b/176822698: dismiss-only state will be removed in the future
@@ -102,17 +100,18 @@ open class PipAppHelper(instrumentation: Instrumentation) : StandardAppHelper(
clickObject(MEDIA_SESSION_START_RADIO_BUTTON_ID)
}
- fun checkWithCustomActionsCheckbox() = uiDevice
- .findObject(By.res(`package`, WITH_CUSTOM_ACTIONS_BUTTON_ID))
- ?.takeIf { it.isCheckable }
- ?.apply { if (!isChecked) clickObject(WITH_CUSTOM_ACTIONS_BUTTON_ID) }
- ?: error("'With custom actions' checkbox not found")
+ fun checkWithCustomActionsCheckbox() =
+ uiDevice
+ .findObject(By.res(`package`, WITH_CUSTOM_ACTIONS_BUTTON_ID))
+ ?.takeIf { it.isCheckable }
+ ?.apply { if (!isChecked) clickObject(WITH_CUSTOM_ACTIONS_BUTTON_ID) }
+ ?: error("'With custom actions' checkbox not found")
- fun pauseMedia() = mediaController?.transportControls?.pause()
- ?: error("No active media session found")
+ fun pauseMedia() =
+ mediaController?.transportControls?.pause() ?: error("No active media session found")
- fun stopMedia() = mediaController?.transportControls?.stop()
- ?: error("No active media session found")
+ fun stopMedia() =
+ mediaController?.transportControls?.stop() ?: error("No active media session found")
@Deprecated(
"Use PipAppHelper.closePipWindow(wmHelper) instead",
@@ -124,55 +123,41 @@ open class PipAppHelper(instrumentation: Instrumentation) : StandardAppHelper(
private fun getWindowRect(wmHelper: WindowManagerStateHelper): Rect {
val windowRegion = wmHelper.getWindowRegion(this)
- require(!windowRegion.isEmpty) {
- "Unable to find a PIP window in the current state"
- }
+ require(!windowRegion.isEmpty) { "Unable to find a PIP window in the current state" }
return windowRegion.bounds
}
- /**
- * Taps the pip window and dismisses it by clicking on the X button.
- */
+ /** Taps the pip window and dismisses it by clicking on the X button. */
open fun closePipWindow(wmHelper: WindowManagerStateHelper) {
val windowRect = getWindowRect(wmHelper)
uiDevice.click(windowRect.centerX(), windowRect.centerY())
// search and interact with the dismiss button
val dismissSelector = By.res(SYSTEMUI_PACKAGE, "dismiss")
uiDevice.wait(Until.hasObject(dismissSelector), FIND_TIMEOUT)
- val dismissPipObject = uiDevice.findObject(dismissSelector)
- ?: error("PIP window dismiss button not found")
+ val dismissPipObject =
+ uiDevice.findObject(dismissSelector) ?: error("PIP window dismiss button not found")
val dismissButtonBounds = dismissPipObject.visibleBounds
uiDevice.click(dismissButtonBounds.centerX(), dismissButtonBounds.centerY())
// Wait for animation to complete.
- wmHelper.StateSyncBuilder()
- .withPipGone()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withPipGone().withHomeActivityVisible().waitForAndVerify()
}
- /**
- * Close the pip window by pressing the expand button
- */
+ /** Close the pip window by pressing the expand button */
fun expandPipWindowToApp(wmHelper: WindowManagerStateHelper) {
val windowRect = getWindowRect(wmHelper)
uiDevice.click(windowRect.centerX(), windowRect.centerY())
// search and interact with the expand button
val expandSelector = By.res(SYSTEMUI_PACKAGE, "expand_button")
uiDevice.wait(Until.hasObject(expandSelector), FIND_TIMEOUT)
- val expandPipObject = uiDevice.findObject(expandSelector)
- ?: error("PIP window expand button not found")
+ val expandPipObject =
+ uiDevice.findObject(expandSelector) ?: error("PIP window expand button not found")
val expandButtonBounds = expandPipObject.visibleBounds
uiDevice.click(expandButtonBounds.centerX(), expandButtonBounds.centerY())
- wmHelper.StateSyncBuilder()
- .withPipGone()
- .withFullScreenApp(this)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withPipGone().withFullScreenApp(this).waitForAndVerify()
}
- /**
- * Double click on the PIP window to expand it
- */
+ /** Double click on the PIP window to expand it */
fun doubleClickPipWindow(wmHelper: WindowManagerStateHelper) {
val windowRect = getWindowRect(wmHelper)
Log.d(TAG, "First click")
@@ -180,9 +165,7 @@ open class PipAppHelper(instrumentation: Instrumentation) : StandardAppHelper(
Log.d(TAG, "Second click")
uiDevice.click(windowRect.centerX(), windowRect.centerY())
Log.d(TAG, "Wait for app transition to end")
- wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
waitForPipWindowToExpandFrom(wmHelper, Region.from(windowRect))
}
@@ -190,13 +173,18 @@ open class PipAppHelper(instrumentation: Instrumentation) : StandardAppHelper(
wmHelper: WindowManagerStateHelper,
windowRect: Region
) {
- wmHelper.StateSyncBuilder().add("pipWindowExpanded") {
- val pipAppWindow = it.wmState.visibleWindows.firstOrNull { window ->
- this.windowMatchesAnyOf(window)
- } ?: return@add false
- val pipRegion = pipAppWindow.frameRegion
- return@add pipRegion.coversMoreThan(windowRect)
- }.waitForAndVerify()
+ wmHelper
+ .StateSyncBuilder()
+ .add("pipWindowExpanded") {
+ val pipAppWindow =
+ it.wmState.visibleWindows.firstOrNull { window ->
+ this.windowMatchesAnyOf(window)
+ }
+ ?: return@add false
+ val pipRegion = pipAppWindow.frameRegion
+ return@add pipRegion.coversMoreThan(windowRect)
+ }
+ .waitForAndVerify()
}
companion object {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
index fc1ff7c84675..c90435223469 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SeamlessRotationAppHelper.kt
@@ -23,7 +23,9 @@ import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
-class SeamlessRotationAppHelper @JvmOverloads constructor(
+class SeamlessRotationAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.SeamlessRotation.LABEL,
component: ComponentNameMatcher =
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
index 0e1df411d394..de152cb5bbc9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ShowWhenLockedAppHelper.kt
@@ -23,7 +23,9 @@ import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
-class ShowWhenLockedAppHelper @JvmOverloads constructor(
+class ShowWhenLockedAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.ShowWhenLockedActivity.LABEL,
component: ComponentNameMatcher =
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
index e3461a74b4ce..e41599002a01 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/SimpleAppHelper.kt
@@ -23,11 +23,12 @@ import com.android.server.wm.flicker.testapp.ActivityOptions
import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
-class SimpleAppHelper @JvmOverloads constructor(
+class SimpleAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.SimpleActivity.LABEL,
- component: ComponentNameMatcher =
- ActivityOptions.SimpleActivity.COMPONENT.toFlickerComponent(),
+ component: ComponentNameMatcher = ActivityOptions.SimpleActivity.COMPONENT.toFlickerComponent(),
launcherStrategy: ILauncherStrategy =
LauncherStrategyFactory.getInstance(instr).launcherStrategy
) : StandardAppHelper(instr, launcherName, component, launcherStrategy)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
index f4ea37f2127a..13301906187d 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/TwoActivitiesAppHelper.kt
@@ -27,7 +27,9 @@ import com.android.server.wm.traces.common.ComponentNameMatcher
import com.android.server.wm.traces.parser.toFlickerComponent
import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper
-class TwoActivitiesAppHelper @JvmOverloads constructor(
+class TwoActivitiesAppHelper
+@JvmOverloads
+constructor(
instr: Instrumentation,
launcherName: String = ActivityOptions.LaunchNewActivity.LABEL,
component: ComponentNameMatcher =
@@ -50,9 +52,7 @@ class TwoActivitiesAppHelper @JvmOverloads constructor(
button.click()
device.wait(Until.gone(launchActivityButton), FIND_TIMEOUT)
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(secondActivityComponent)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withFullScreenApp(secondActivityComponent).waitForAndVerify()
}
companion object {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
index 9b8d791e0892..1a495957bb7f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToAppTest.kt
@@ -37,10 +37,10 @@ import org.junit.runners.Parameterized
* Test IME window closing back to app window transitions.
*
* This test doesn't work on 90 degrees. According to the InputMethodService documentation:
- *
+ * ```
* Don't show if this is not explicitly requested by the user and the input method
* is fullscreen. That would be too disruptive.
- *
+ * ```
* More details on b/190352379
*
* To run this test: `atest FlickerTests:CloseImeAutoOpenWindowToAppTest`
@@ -54,51 +54,35 @@ class CloseImeAutoOpenWindowToAppTest(testSpec: FlickerTestParameter) : BaseTest
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit = {
- setup {
- testApp.launchViaIntent(wmHelper)
- }
- teardown {
- testApp.exit(wmHelper)
- }
- transitions {
- testApp.closeIME(wmHelper)
- }
+ setup { testApp.launchViaIntent(wmHelper) }
+ teardown { testApp.exit(wmHelper) }
+ transitions { testApp.closeIME(wmHelper) }
}
@Presubmit
@Test
fun imeAppWindowIsAlwaysVisible() {
- testSpec.assertWm {
- this.isAppWindowOnTop(testApp)
- }
+ testSpec.assertWm { this.isAppWindowOnTop(testApp) }
}
@Presubmit
@Test
fun imeLayerVisibleStart() {
- testSpec.assertLayersStart {
- this.isVisible(ComponentNameMatcher.IME)
- }
+ testSpec.assertLayersStart { this.isVisible(ComponentNameMatcher.IME) }
}
@Presubmit
@Test
fun imeLayerInvisibleEnd() {
- testSpec.assertLayersEnd {
- this.isInvisible(ComponentNameMatcher.IME)
- }
+ testSpec.assertLayersEnd { this.isInvisible(ComponentNameMatcher.IME) }
}
- @Presubmit
- @Test
- fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
+ @Presubmit @Test fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
@Presubmit
@Test
fun imeAppLayerIsAlwaysVisible() {
- testSpec.assertLayers {
- this.isVisible(testApp)
- }
+ testSpec.assertLayers { this.isVisible(testApp) }
}
companion object {
@@ -107,12 +91,13 @@ class CloseImeAutoOpenWindowToAppTest(testSpec: FlickerTestParameter) : BaseTest
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
- // b/190352379 (IME doesn't show on app launch in 90 degrees)
+ // b/190352379 (IME doesn't show on app launch in 90 degrees)
supportedRotations = listOf(Surface.ROTATION_0),
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- )
+ supportedNavigationModes =
+ listOf(
+ WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
+ WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
+ )
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
index e2d3eb8860fc..463efe89b5e9 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeAutoOpenWindowToHomeTest.kt
@@ -37,10 +37,10 @@ import org.junit.runners.Parameterized
* Test IME window closing back to app window transitions.
*
* This test doesn't work on 90 degrees. According to the InputMethodService documentation:
- *
+ * ```
* Don't show if this is not explicitly requested by the user and the input method
* is fullscreen. That would be too disruptive.
- *
+ * ```
* More details on b/190352379
*
* To run this test: `atest FlickerTests:CloseImeAutoOpenWindowToHomeTest`
@@ -58,56 +58,37 @@ class CloseImeAutoOpenWindowToHomeTest(testSpec: FlickerTestParameter) : BaseTes
tapl.setExpectedRotationCheckEnabled(false)
testApp.launchViaIntent(wmHelper)
}
- teardown {
- testApp.exit(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
transitions {
tapl.goHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .withImeGone()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().withImeGone().waitForAndVerify()
}
}
@Presubmit
@Test
fun imeAppWindowBecomesInvisible() {
- testSpec.assertWm {
- this.isAppWindowOnTop(testApp)
- .then()
- .isAppWindowNotOnTop(testApp)
- }
+ testSpec.assertWm { this.isAppWindowOnTop(testApp).then().isAppWindowNotOnTop(testApp) }
}
@Presubmit
@Test
fun imeLayerVisibleStart() {
- testSpec.assertLayersStart {
- this.isVisible(ComponentNameMatcher.IME)
- }
+ testSpec.assertLayersStart { this.isVisible(ComponentNameMatcher.IME) }
}
@Presubmit
@Test
fun imeLayerInvisibleEnd() {
- testSpec.assertLayersEnd {
- this.isInvisible(ComponentNameMatcher.IME)
- }
+ testSpec.assertLayersEnd { this.isInvisible(ComponentNameMatcher.IME) }
}
- @Presubmit
- @Test
- fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
+ @Presubmit @Test fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
@Presubmit
@Test
fun imeAppLayerBecomesInvisible() {
- testSpec.assertLayers {
- this.isVisible(testApp)
- .then()
- .isInvisible(testApp)
- }
+ testSpec.assertLayers { this.isVisible(testApp).then().isInvisible(testApp) }
}
companion object {
@@ -118,9 +99,11 @@ class CloseImeAutoOpenWindowToHomeTest(testSpec: FlickerTestParameter) : BaseTes
.getConfigNonRotationTests(
// b/190352379 (IME doesn't show on app launch in 90 degrees)
supportedRotations = listOf(Surface.ROTATION_0),
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY)
+ supportedNavigationModes =
+ listOf(
+ WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
+ WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
+ )
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt
index 923ed5e1bc34..91d9a1f17d05 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeEditorPopupDialogTest.kt
@@ -16,7 +16,7 @@
package com.android.server.wm.flicker.ime
-import android.platform.test.annotations.Postsubmit
+import android.platform.test.annotations.Presubmit
import android.view.Surface
import android.view.WindowManagerPolicyConstants
import androidx.test.filters.RequiresDevice
@@ -50,47 +50,20 @@ class CloseImeEditorPopupDialogTest(testSpec: FlickerTestParameter) : BaseTest(t
}
transitions {
imeTestApp.dismissDialog(wmHelper)
- wmHelper.StateSyncBuilder()
- .withImeGone()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withImeGone().waitForAndVerify()
}
teardown {
tapl.goHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
imeTestApp.exit(wmHelper)
}
}
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() =
- super.taskBarLayerIsVisibleAtStartAndEnd()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
- super.visibleLayersShownMoreThanOneConsecutiveEntry()
-
- /** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
- super.visibleWindowsShownMoreThanOneConsecutiveEntry()
-
- @Postsubmit
+ @Presubmit
@Test
fun imeWindowBecameInvisible() = testSpec.imeWindowBecomesInvisible()
- @Postsubmit
+ @Presubmit
@Test
fun imeLayerAndImeSnapshotVisibleOnScreen() {
testSpec.assertLayers {
@@ -103,20 +76,23 @@ class CloseImeEditorPopupDialogTest(testSpec: FlickerTestParameter) : BaseTest(t
}
}
- @Postsubmit
+ @Presubmit
@Test
fun imeSnapshotAssociatedOnAppVisibleRegion() {
testSpec.assertLayers {
this.invoke("imeSnapshotAssociatedOnAppVisibleRegion") {
- val imeSnapshotLayers = it.subjects.filter { subject ->
- subject.name.contains(
- ComponentNameMatcher.IME_SNAPSHOT.toLayerName()
- ) && subject.isVisible
- }
+ val imeSnapshotLayers =
+ it.subjects.filter { subject ->
+ subject.name.contains(ComponentNameMatcher.IME_SNAPSHOT.toLayerName()) &&
+ subject.isVisible
+ }
if (imeSnapshotLayers.isNotEmpty()) {
- val visibleAreas = imeSnapshotLayers.mapNotNull { imeSnapshotLayer ->
- imeSnapshotLayer.layer?.visibleRegion
- }.toTypedArray()
+ val visibleAreas =
+ imeSnapshotLayers
+ .mapNotNull { imeSnapshotLayer ->
+ imeSnapshotLayer.layer?.visibleRegion
+ }
+ .toTypedArray()
val imeVisibleRegion = RegionSubject.assertThat(visibleAreas, this, timestamp)
val appVisibleRegion = it.visibleRegion(imeTestApp)
if (imeVisibleRegion.region.isNotEmpty) {
@@ -133,7 +109,8 @@ class CloseImeEditorPopupDialogTest(testSpec: FlickerTestParameter) : BaseTest(t
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
- supportedNavigationModes = listOf(
+ supportedNavigationModes =
+ listOf(
WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
),
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
index 32efbb0ea1cb..b9c875ab5938 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToAppTest.kt
@@ -35,8 +35,8 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME window closing back to app window transitions.
- * To run this test: `atest FlickerTests:CloseImeWindowToAppTest`
+ * Test IME window closing back to app window transitions. To run this test: `atest
+ * FlickerTests:CloseImeWindowToAppTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -51,12 +51,8 @@ class CloseImeWindowToAppTest(testSpec: FlickerTestParameter) : BaseTest(testSpe
testApp.launchViaIntent(wmHelper)
testApp.openIME(wmHelper)
}
- teardown {
- testApp.exit(wmHelper)
- }
- transitions {
- testApp.closeIME(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
+ transitions { testApp.closeIME(wmHelper) }
}
/** {@inheritDoc} */
@@ -64,10 +60,13 @@ class CloseImeWindowToAppTest(testSpec: FlickerTestParameter) : BaseTest(testSpe
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() {
testSpec.assertWm {
- this.visibleWindowsShownMoreThanOneConsecutiveEntry(listOf(
- ComponentNameMatcher.IME,
- ComponentNameMatcher.SPLASH_SCREEN,
- ComponentNameMatcher.SNAPSHOT))
+ this.visibleWindowsShownMoreThanOneConsecutiveEntry(
+ listOf(
+ ComponentNameMatcher.IME,
+ ComponentNameMatcher.SPLASH_SCREEN,
+ ComponentNameMatcher.SNAPSHOT
+ )
+ )
}
}
@@ -88,32 +87,25 @@ class CloseImeWindowToAppTest(testSpec: FlickerTestParameter) : BaseTest(testSpe
testSpec.navBarLayerPositionAtStartAndEnd()
}
- @Presubmit
- @Test
- fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
+ @Presubmit @Test fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
@Presubmit
@Test
fun imeAppLayerIsAlwaysVisible() {
- testSpec.assertLayers {
- this.isVisible(testApp)
- }
+ testSpec.assertLayers { this.isVisible(testApp) }
}
@Presubmit
@Test
fun imeAppWindowIsAlwaysVisible() {
- testSpec.assertWm {
- this.isAppWindowOnTop(testApp)
- }
+ testSpec.assertWm { this.isAppWindowOnTop(testApp) }
}
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
index 177e76104b3d..1dc3ca55caba 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CloseImeWindowToHomeTest.kt
@@ -34,8 +34,8 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME window closing to home transitions.
- * To run this test: `atest FlickerTests:CloseImeWindowToHomeTest`
+ * Test IME window closing to home transitions. To run this test: `atest
+ * FlickerTests:CloseImeWindowToHomeTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -53,14 +53,9 @@ class CloseImeWindowToHomeTest(testSpec: FlickerTestParameter) : BaseTest(testSp
}
transitions {
tapl.goHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .withImeGone()
- .waitForAndVerify()
- }
- teardown {
- testApp.exit(wmHelper)
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().withImeGone().waitForAndVerify()
}
+ teardown { testApp.exit(wmHelper) }
}
/** {@inheritDoc} */
@@ -84,40 +79,25 @@ class CloseImeWindowToHomeTest(testSpec: FlickerTestParameter) : BaseTest(testSp
override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
testSpec.assertLayers {
this.visibleLayersShownMoreThanOneConsecutiveEntry(
- listOf(
- ComponentNameMatcher.IME,
- ComponentNameMatcher.SPLASH_SCREEN
- )
+ listOf(ComponentNameMatcher.IME, ComponentNameMatcher.SPLASH_SCREEN)
)
}
}
- @Presubmit
- @Test
- fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
+ @Presubmit @Test fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
- @Presubmit
- @Test
- fun imeWindowBecomesInvisible() = testSpec.imeWindowBecomesInvisible()
+ @Presubmit @Test fun imeWindowBecomesInvisible() = testSpec.imeWindowBecomesInvisible()
@Presubmit
@Test
fun imeAppWindowBecomesInvisible() {
- testSpec.assertWm {
- this.isAppWindowVisible(testApp)
- .then()
- .isAppWindowInvisible(testApp)
- }
+ testSpec.assertWm { this.isAppWindowVisible(testApp).then().isAppWindowInvisible(testApp) }
}
@Presubmit
@Test
fun imeAppLayerBecomesInvisible() {
- testSpec.assertLayers {
- this.isVisible(testApp)
- .then()
- .isInvisible(testApp)
- }
+ testSpec.assertLayers { this.isVisible(testApp).then().isInvisible(testApp) }
}
companion object {
@@ -126,11 +106,12 @@ class CloseImeWindowToHomeTest(testSpec: FlickerTestParameter) : BaseTest(testSp
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
- supportedRotations = listOf(Surface.ROTATION_0),
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- )
+ supportedRotations = listOf(Surface.ROTATION_0),
+ supportedNavigationModes =
+ listOf(
+ WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
+ WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
+ )
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
index 9c99d966e345..e0c5edcec762 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/CommonAssertions.kt
@@ -15,6 +15,7 @@
*/
@file:JvmName("CommonAssertions")
+
package com.android.server.wm.flicker.ime
import com.android.server.wm.flicker.FlickerTestParameter
@@ -22,17 +23,13 @@ import com.android.server.wm.traces.common.ComponentNameMatcher
fun FlickerTestParameter.imeLayerBecomesVisible() {
assertLayers {
- this.isInvisible(ComponentNameMatcher.IME)
- .then()
- .isVisible(ComponentNameMatcher.IME)
+ this.isInvisible(ComponentNameMatcher.IME).then().isVisible(ComponentNameMatcher.IME)
}
}
fun FlickerTestParameter.imeLayerBecomesInvisible() {
assertLayers {
- this.isVisible(ComponentNameMatcher.IME)
- .then()
- .isInvisible(ComponentNameMatcher.IME)
+ this.isVisible(ComponentNameMatcher.IME).then().isInvisible(ComponentNameMatcher.IME)
}
}
@@ -46,9 +43,7 @@ fun FlickerTestParameter.imeWindowIsAlwaysVisible(rotatesScreen: Boolean = false
.isNonAppWindowVisible(ComponentNameMatcher.IME)
}
} else {
- assertWm {
- this.isNonAppWindowVisible(ComponentNameMatcher.IME)
- }
+ assertWm { this.isNonAppWindowVisible(ComponentNameMatcher.IME) }
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt
index f0776c10bd69..073da4f092dc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeAndDialogThemeAppTest.kt
@@ -47,30 +47,22 @@ import org.junit.runners.Parameterized
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class LaunchAppShowImeAndDialogThemeAppTest(
- testSpec: FlickerTestParameter
-) : BaseTest(testSpec) {
+class LaunchAppShowImeAndDialogThemeAppTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
private val testApp = ImeAppAutoFocusHelper(instrumentation, testSpec.startRotation)
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit = {
setup {
testApp.launchViaIntent(wmHelper)
- wmHelper.StateSyncBuilder()
- .withImeShown()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withImeShown().waitForAndVerify()
testApp.startDialogThemedActivity(wmHelper)
// Verify IME insets isn't visible on dialog since it's non-IME focusable window
assertFalse(testApp.getInsetsVisibleFromDialog(ime()))
assertTrue(testApp.getInsetsVisibleFromDialog(statusBars()))
assertTrue(testApp.getInsetsVisibleFromDialog(navigationBars()))
}
- teardown {
- testApp.exit(wmHelper)
- }
- transitions {
- testApp.dismissDialog(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
+ transitions { testApp.dismissDialog(wmHelper) }
}
/** {@inheritDoc} */
@@ -83,41 +75,29 @@ class LaunchAppShowImeAndDialogThemeAppTest(
@Test
override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
- /**
- * Checks that [ComponentMatcher.IME] layer becomes visible during the transition
- */
- @Presubmit
- @Test
- fun imeWindowIsAlwaysVisible() = testSpec.imeWindowIsAlwaysVisible()
+ /** Checks that [ComponentMatcher.IME] layer becomes visible during the transition */
+ @Presubmit @Test fun imeWindowIsAlwaysVisible() = testSpec.imeWindowIsAlwaysVisible()
- /**
- * Checks that [ComponentMatcher.IME] layer is visible at the end of the transition
- */
+ /** Checks that [ComponentMatcher.IME] layer is visible at the end of the transition */
@Presubmit
@Test
fun imeLayerExistsEnd() {
- testSpec.assertLayersEnd {
- this.isVisible(ComponentNameMatcher.IME)
- }
+ testSpec.assertLayersEnd { this.isVisible(ComponentNameMatcher.IME) }
}
- /**
- * Checks that [ComponentMatcher.IME_SNAPSHOT] layer is invisible always.
- */
+ /** Checks that [ComponentMatcher.IME_SNAPSHOT] layer is invisible always. */
@Presubmit
@Test
fun imeSnapshotNotVisible() {
- testSpec.assertLayers {
- this.isInvisible(ComponentNameMatcher.IME_SNAPSHOT)
- }
+ testSpec.assertLayers { this.isInvisible(ComponentNameMatcher.IME_SNAPSHOT) }
}
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
@@ -125,10 +105,11 @@ class LaunchAppShowImeAndDialogThemeAppTest(
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
supportedRotations = listOf(Surface.ROTATION_0),
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- )
+ supportedNavigationModes =
+ listOf(
+ WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
+ WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
+ )
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt
index 85e9e75776fb..a93f1766b05f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/LaunchAppShowImeOnStartTest.kt
@@ -41,27 +41,33 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:LaunchAppShowImeOnStartTest`
*
* Actions:
+ * ```
* Make sure no apps are running on the device
* Launch an app [testApp] that automatically displays IME and wait animation to complete
- *
+ * ```
* To run only the presubmit assertions add: `--
+ * ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
- *
+ * ```
* To run only the postsubmit assertions add: `--
+ * ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
- *
+ * ```
* To run only the flaky assertions add: `--
+ * ```
* --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [CloseAppTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -83,65 +89,48 @@ class LaunchAppShowImeOnStartTest(testSpec: FlickerTestParameter) : BaseTest(tes
}
transitions {
testApp.launchViaIntent(wmHelper)
- wmHelper.StateSyncBuilder()
- .withImeShown()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withImeShown().waitForAndVerify()
}
}
- /**
- * Checks that [ComponentMatcher.IME] window becomes visible during the transition
- */
- @Presubmit
- @Test
- fun imeWindowBecomesVisible() = testSpec.imeWindowBecomesVisible()
+ /** Checks that [ComponentMatcher.IME] window becomes visible during the transition */
+ @Presubmit @Test fun imeWindowBecomesVisible() = testSpec.imeWindowBecomesVisible()
- /**
- * Checks that [ComponentMatcher.IME] layer becomes visible during the transition
- */
- @Presubmit
- @Test
- fun imeLayerBecomesVisible() = testSpec.imeLayerBecomesVisible()
+ /** Checks that [ComponentMatcher.IME] layer becomes visible during the transition */
+ @Presubmit @Test fun imeLayerBecomesVisible() = testSpec.imeLayerBecomesVisible()
- /**
- * Checks that [ComponentMatcher.IME] layer is invisible at the start of the transition
- */
+ /** Checks that [ComponentMatcher.IME] layer is invisible at the start of the transition */
@Presubmit
@Test
fun imeLayerNotExistsStart() {
- testSpec.assertLayersStart {
- this.isInvisible(ComponentNameMatcher.IME)
- }
+ testSpec.assertLayersStart { this.isInvisible(ComponentNameMatcher.IME) }
}
- /**
- * Checks that [ComponentMatcher.IME] layer is visible at the end of the transition
- */
+ /** Checks that [ComponentMatcher.IME] layer is visible at the end of the transition */
@Presubmit
@Test
fun imeLayerExistsEnd() {
- testSpec.assertLayersEnd {
- this.isVisible(ComponentNameMatcher.IME)
- }
+ testSpec.assertLayersEnd { this.isVisible(ComponentNameMatcher.IME) }
}
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
- supportedRotations = listOf(Surface.ROTATION_0),
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- )
+ supportedRotations = listOf(Surface.ROTATION_0),
+ supportedNavigationModes =
+ listOf(
+ WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
+ WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
+ )
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowAndCloseTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowAndCloseTest.kt
index 36bc6a3e8ed2..a6bd791282b8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowAndCloseTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowAndCloseTest.kt
@@ -57,21 +57,13 @@ class OpenImeWindowAndCloseTest(testSpec: FlickerTestParameter) : BaseTest(testS
testApp.launchViaIntent(wmHelper)
testApp.openIME(wmHelper)
}
- transitions {
- testApp.finishActivity(wmHelper)
- }
- teardown {
- simpleApp.exit(wmHelper)
- }
+ transitions { testApp.finishActivity(wmHelper) }
+ teardown { simpleApp.exit(wmHelper) }
}
- @Presubmit
- @Test
- fun imeWindowBecomesInvisible() = testSpec.imeWindowBecomesInvisible()
+ @Presubmit @Test fun imeWindowBecomesInvisible() = testSpec.imeWindowBecomesInvisible()
- @Presubmit
- @Test
- fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
+ @Presubmit @Test fun imeLayerBecomesInvisible() = testSpec.imeLayerBecomesInvisible()
@Presubmit
@Test
@@ -93,11 +85,12 @@ class OpenImeWindowAndCloseTest(testSpec: FlickerTestParameter) : BaseTest(testS
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
- supportedRotations = listOf(Surface.ROTATION_0),
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- )
+ supportedRotations = listOf(Surface.ROTATION_0),
+ supportedNavigationModes =
+ listOf(
+ WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
+ WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
+ )
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt
index 7d98d06fcbd4..3e18d5957eb7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowFromFixedOrientationAppTest.kt
@@ -27,8 +27,10 @@ import com.android.server.wm.flicker.FlickerTestParameter
import com.android.server.wm.flicker.FlickerTestParameterFactory
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.ImeAppAutoFocusHelper
+import com.android.server.wm.flicker.helpers.isShellTransitionsEnabled
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.snapshotStartingWindowLayerCoversExactlyOnApp
+import org.junit.Assume
import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
@@ -37,16 +39,15 @@ import org.junit.runners.Parameterized
/**
* Test IME window layer will become visible when switching from the fixed orientation activity
- * (e.g. Launcher activity).
- * To run this test: `atest FlickerTests:OpenImeWindowFromFixedOrientationAppTest`
+ * (e.g. Launcher activity). To run this test: `atest
+ * FlickerTests:OpenImeWindowFromFixedOrientationAppTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenImeWindowFromFixedOrientationAppTest(
- testSpec: FlickerTestParameter
-) : BaseTest(testSpec) {
+class OpenImeWindowFromFixedOrientationAppTest(testSpec: FlickerTestParameter) :
+ BaseTest(testSpec) {
private val imeTestApp = ImeAppAutoFocusHelper(instrumentation, testSpec.startRotation)
/** {@inheritDoc} */
@@ -59,18 +60,14 @@ class OpenImeWindowFromFixedOrientationAppTest(
// Swiping out the IME activity to home.
tapl.goHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
}
transitions {
// Bring the exist IME activity to the front in landscape mode device rotation.
setRotation(Surface.ROTATION_90)
imeTestApp.launchViaIntent(wmHelper)
}
- teardown {
- imeTestApp.exit(wmHelper)
- }
+ teardown { imeTestApp.exit(wmHelper) }
}
/** {@inheritDoc} */
@@ -94,6 +91,14 @@ class OpenImeWindowFromFixedOrientationAppTest(
@Postsubmit
@Test
fun snapshotStartingWindowLayerCoversExactlyOnApp() {
+ Assume.assumeFalse(isShellTransitionsEnabled)
+ testSpec.snapshotStartingWindowLayerCoversExactlyOnApp(imeTestApp)
+ }
+
+ @Presubmit
+ @Test
+ fun snapshotStartingWindowLayerCoversExactlyOnApp_ShellTransit() {
+ Assume.assumeTrue(isShellTransitionsEnabled)
testSpec.snapshotStartingWindowLayerCoversExactlyOnApp(imeTestApp)
}
@@ -101,18 +106,17 @@ class OpenImeWindowFromFixedOrientationAppTest(
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
- supportedRotations = listOf(Surface.ROTATION_90),
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- )
+ supportedRotations = listOf(Surface.ROTATION_90),
+ supportedNavigationModes =
+ listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY)
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
index f84bb4faef97..b43efea4c647 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowTest.kt
@@ -32,10 +32,7 @@ import org.junit.runner.RunWith
import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
-/**
- * Test IME window opening transitions.
- * To run this test: `atest FlickerTests:OpenImeWindowTest`
- */
+/** Test IME window opening transitions. To run this test: `atest FlickerTests:OpenImeWindowTest` */
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@@ -45,40 +42,28 @@ class OpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit = {
- setup {
- testApp.launchViaIntent(wmHelper)
- }
- transitions {
- testApp.openIME(wmHelper)
- }
+ setup { testApp.launchViaIntent(wmHelper) }
+ transitions { testApp.openIME(wmHelper) }
teardown {
testApp.closeIME(wmHelper)
testApp.exit(wmHelper)
}
}
- @Presubmit
- @Test
- fun imeWindowBecomesVisible() = testSpec.imeWindowBecomesVisible()
+ @Presubmit @Test fun imeWindowBecomesVisible() = testSpec.imeWindowBecomesVisible()
@Presubmit
@Test
fun appWindowAlwaysVisibleOnTop() {
- testSpec.assertWm {
- this.isAppWindowOnTop(testApp)
- }
+ testSpec.assertWm { this.isAppWindowOnTop(testApp) }
}
- @Presubmit
- @Test
- fun imeLayerBecomesVisible() = testSpec.imeLayerBecomesVisible()
+ @Presubmit @Test fun imeLayerBecomesVisible() = testSpec.imeLayerBecomesVisible()
@Presubmit
@Test
fun layerAlwaysVisible() {
- testSpec.assertLayers {
- this.isVisible(testApp)
- }
+ testSpec.assertLayers { this.isVisible(testApp) }
}
companion object {
@@ -87,11 +72,12 @@ class OpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
- supportedRotations = listOf(Surface.ROTATION_0),
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- )
+ supportedRotations = listOf(Surface.ROTATION_0),
+ supportedNavigationModes =
+ listOf(
+ WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
+ WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
+ )
)
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
index 184a92a32036..0a7701e54b31 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/OpenImeWindowToOverViewTest.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.ime
-import android.platform.test.annotations.Postsubmit
import android.platform.test.annotations.Presubmit
import android.platform.test.annotations.RequiresDevice
import android.view.Surface
@@ -42,8 +41,8 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME window layer will be associated with the app task when going to the overview screen.
- * To run this test: `atest FlickerTests:OpenImeWindowToOverViewTest`
+ * Test IME window layer will be associated with the app task when going to the overview screen. To
+ * run this test: `atest FlickerTests:OpenImeWindowToOverViewTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -54,35 +53,30 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit = {
- setup {
- imeTestApp.launchViaIntent(wmHelper)
- }
+ setup { imeTestApp.launchViaIntent(wmHelper) }
transitions {
device.pressRecentApps()
- val builder = wmHelper.StateSyncBuilder()
- .withRecentsActivityVisible()
+ val builder = wmHelper.StateSyncBuilder().withRecentsActivityVisible()
waitNavStatusBarVisibility(builder)
builder.waitForAndVerify()
}
teardown {
device.pressHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
imeTestApp.exit(wmHelper)
}
}
/**
- * The bars (including [ComponentMatcher.STATUS_BAR] and [ComponentMatcher.NAV_BAR]) are
+ * The bars (including [ComponentNameMatcher.STATUS_BAR] and [ComponentNameMatcher.NAV_BAR]) are
* expected to be hidden while entering overview in landscape if launcher is set to portrait
* only. Because "showing portrait overview (launcher) in landscape display" is an intermediate
* state depending on the touch-up to decide the intention of gesture, the display may keep in
* landscape if return to app, or change to portrait if the gesture is to swipe-to-home.
*
- * So instead of showing landscape bars with portrait launcher at the same time
- * (especially return-to-home that launcher workspace becomes visible), hide the bars until
- * leave overview to have cleaner appearance.
+ * So instead of showing landscape bars with portrait launcher at the same time (especially
+ * return-to-home that launcher workspace becomes visible), hide the bars until leave overview
+ * to have cleaner appearance.
*
* b/227189877
*/
@@ -90,8 +84,7 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
when {
testSpec.isLandscapeOrSeascapeAtStart && !testSpec.isTablet ->
stateSync.add(WindowManagerConditionsFactory.isStatusBarVisible().negate())
- else ->
- stateSync.withNavOrTaskBarVisible().withStatusBarVisible()
+ else -> stateSync.withNavOrTaskBarVisible().withStatusBarVisible()
}
}
@@ -109,9 +102,7 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
testSpec.navBarLayerIsVisibleAtStartAndEnd()
}
- /**
- * Bars are expected to be hidden while entering overview in landscape (b/227189877)
- */
+ /** Bars are expected to be hidden while entering overview in landscape (b/227189877) */
@Presubmit
@Test
fun navBarLayerIsVisibleAtStartAndEndGestural() {
@@ -122,8 +113,8 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
}
/**
- * In the legacy transitions, the nav bar is not marked as invisible.
- * In the new transitions this is fixed and the nav bar shows as invisible
+ * In the legacy transitions, the nav bar is not marked as invisible. In the new transitions
+ * this is fixed and the nav bar shows as invisible
*/
@Presubmit
@Test
@@ -132,17 +123,13 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
Assume.assumeTrue(testSpec.isLandscapeOrSeascapeAtStart)
Assume.assumeTrue(testSpec.isGesturalNavigation)
Assume.assumeTrue(isShellTransitionsEnabled)
- testSpec.assertLayersStart {
- this.isVisible(ComponentNameMatcher.NAV_BAR)
- }
- testSpec.assertLayersEnd {
- this.isInvisible(ComponentNameMatcher.NAV_BAR)
- }
+ testSpec.assertLayersStart { this.isVisible(ComponentNameMatcher.NAV_BAR) }
+ testSpec.assertLayersEnd { this.isInvisible(ComponentNameMatcher.NAV_BAR) }
}
/**
- * In the legacy transitions, the nav bar is not marked as invisible.
- * In the new transitions this is fixed and the nav bar shows as invisible
+ * In the legacy transitions, the nav bar is not marked as invisible. In the new transitions
+ * this is fixed and the nav bar shows as invisible
*/
@Presubmit
@Test
@@ -150,17 +137,13 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
Assume.assumeTrue(testSpec.isLandscapeOrSeascapeAtStart)
Assume.assumeTrue(testSpec.isGesturalNavigation)
Assume.assumeFalse(testSpec.isTablet)
- testSpec.assertLayersStart {
- this.isVisible(ComponentNameMatcher.STATUS_BAR)
- }
- testSpec.assertLayersEnd {
- this.isInvisible(ComponentNameMatcher.STATUS_BAR)
- }
+ testSpec.assertLayersStart { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
+ testSpec.assertLayersEnd { this.isInvisible(ComponentNameMatcher.STATUS_BAR) }
}
/**
- * In the legacy transitions, the nav bar is not marked as invisible.
- * In the new transitions this is fixed and the nav bar shows as invisible
+ * In the legacy transitions, the nav bar is not marked as invisible. In the new transitions
+ * this is fixed and the nav bar shows as invisible
*/
@Presubmit
@Test
@@ -174,27 +157,30 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
/** {@inheritDoc} */
@Test
@Ignore("Visibility changes depending on orientation and navigation mode")
- override fun navBarLayerIsVisibleAtStartAndEnd() { }
+ override fun navBarLayerIsVisibleAtStartAndEnd() {
+ }
/** {@inheritDoc} */
@Test
@Ignore("Visibility changes depending on orientation and navigation mode")
- override fun navBarLayerPositionAtStartAndEnd() { }
+ override fun navBarLayerPositionAtStartAndEnd() {
+ }
/** {@inheritDoc} */
@Test
@Ignore("Visibility changes depending on orientation and navigation mode")
- override fun statusBarLayerPositionAtStartAndEnd() { }
+ override fun statusBarLayerPositionAtStartAndEnd() {
+ }
/** {@inheritDoc} */
@Test
@Ignore("Visibility changes depending on orientation and navigation mode")
- override fun statusBarLayerIsVisibleAtStartAndEnd() { }
+ override fun statusBarLayerIsVisibleAtStartAndEnd() {
+ }
- @Postsubmit
+ @Presubmit
@Test
- override fun taskBarLayerIsVisibleAtStartAndEnd() =
- super.taskBarLayerIsVisibleAtStartAndEnd()
+ override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
@Presubmit
@Test
@@ -209,12 +195,8 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
Assume.assumeTrue(testSpec.isLandscapeOrSeascapeAtStart)
Assume.assumeFalse(testSpec.isTablet)
Assume.assumeTrue(isShellTransitionsEnabled)
- testSpec.assertLayersStart {
- this.isVisible(ComponentNameMatcher.STATUS_BAR)
- }
- testSpec.assertLayersEnd {
- this.isInvisible(ComponentNameMatcher.STATUS_BAR)
- }
+ testSpec.assertLayersStart { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
+ testSpec.assertLayersEnd { this.isInvisible(ComponentNameMatcher.STATUS_BAR) }
}
@Presubmit
@@ -230,11 +212,9 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Test
fun imeLayerIsVisibleAndAssociatedWithAppWidow() {
testSpec.assertLayersStart {
- isVisible(ComponentNameMatcher.IME).visibleRegion(ComponentNameMatcher.IME)
- .coversAtMost(
- isVisible(imeTestApp)
- .visibleRegion(imeTestApp).region
- )
+ isVisible(ComponentNameMatcher.IME)
+ .visibleRegion(ComponentNameMatcher.IME)
+ .coversAtMost(isVisible(imeTestApp).visibleRegion(imeTestApp).region)
}
testSpec.assertLayers {
this.invoke("imeLayerIsVisibleAndAlignAppWidow") {
@@ -252,8 +232,8 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
@@ -261,7 +241,8 @@ class OpenImeWindowToOverViewTest(testSpec: FlickerTestParameter) : BaseTest(tes
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90),
- supportedNavigationModes = listOf(
+ supportedNavigationModes =
+ listOf(
WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY,
WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index ddf61bfd34a1..4c476848ecd1 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -35,8 +35,7 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME window opening transitions.
- * To run this test: `atest FlickerTests:ReOpenImeWindowTest`
+ * Test IME window opening transitions. To run this test: `atest FlickerTests:ReOpenImeWindowTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -48,24 +47,17 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit = {
setup {
- testApp.launchViaIntent(wmHelper)
- testApp.openIME(wmHelper)
- this.setRotation(testSpec.startRotation)
- device.pressRecentApps()
- wmHelper.StateSyncBuilder()
- .withRecentsActivityVisible()
- .waitForAndVerify()
+ testApp.launchViaIntent(wmHelper)
+ testApp.openIME(wmHelper)
+ this.setRotation(testSpec.startRotation)
+ device.pressRecentApps()
+ wmHelper.StateSyncBuilder().withRecentsActivityVisible().waitForAndVerify()
}
transitions {
device.reopenAppFromOverview(wmHelper)
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(testApp)
- .withImeShown()
- .waitForAndVerify()
- }
- teardown {
- testApp.exit(wmHelper)
+ wmHelper.StateSyncBuilder().withFullScreenApp(testApp).withImeShown().waitForAndVerify()
}
+ teardown { testApp.exit(wmHelper) }
}
/** {@inheritDoc} */
@@ -77,8 +69,11 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
val recentTaskComponent = ComponentNameMatcher("", "RecentTaskScreenshotSurface")
testSpec.assertLayers {
this.visibleLayersShownMoreThanOneConsecutiveEntry(
- listOf(ComponentNameMatcher.SPLASH_SCREEN,
- ComponentNameMatcher.SNAPSHOT, recentTaskComponent)
+ listOf(
+ ComponentNameMatcher.SPLASH_SCREEN,
+ ComponentNameMatcher.SNAPSHOT,
+ recentTaskComponent
+ )
)
}
}
@@ -90,9 +85,12 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
val component = ComponentNameMatcher("", "RecentTaskScreenshotSurface")
testSpec.assertWm {
this.visibleWindowsShownMoreThanOneConsecutiveEntry(
- ignoreWindows = listOf(ComponentNameMatcher.SPLASH_SCREEN,
+ ignoreWindows =
+ listOf(
+ ComponentNameMatcher.SPLASH_SCREEN,
ComponentNameMatcher.SNAPSHOT,
- component)
+ component
+ )
)
}
}
@@ -102,14 +100,12 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
fun launcherWindowBecomesInvisible() {
testSpec.assertWm {
this.isAppWindowVisible(ComponentNameMatcher.LAUNCHER)
- .then()
- .isAppWindowInvisible(ComponentNameMatcher.LAUNCHER)
+ .then()
+ .isAppWindowInvisible(ComponentNameMatcher.LAUNCHER)
}
}
- @Presubmit
- @Test
- fun imeWindowIsAlwaysVisible() = testSpec.imeWindowIsAlwaysVisible()
+ @Presubmit @Test fun imeWindowIsAlwaysVisible() = testSpec.imeWindowIsAlwaysVisible()
@Presubmit
@Test
@@ -118,17 +114,13 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
// and exiting overview. Since we log 1x per frame, sometimes the activity visibility
// and the app visibility are updated together, sometimes not, thus ignore activity
// check at the start
- testSpec.assertWm {
- this.isAppWindowVisible(testApp)
- }
+ testSpec.assertWm { this.isAppWindowVisible(testApp) }
}
@Presubmit
@Test
fun imeLayerBecomesVisible() {
- testSpec.assertLayers {
- this.isVisible(ComponentNameMatcher.IME)
- }
+ testSpec.assertLayers { this.isVisible(ComponentNameMatcher.IME) }
}
@Presubmit
@@ -148,9 +140,7 @@ open class ReOpenImeWindowTest(testSpec: FlickerTestParameter) : BaseTest(testSp
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(
- supportedRotations = listOf(Surface.ROTATION_0)
- )
+ .getConfigNonRotationTests(supportedRotations = listOf(Surface.ROTATION_0))
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
index 65f51e0dc834..02b3b1398e50 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest.kt
@@ -41,17 +41,15 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME windows switching with 2-Buttons or gestural navigation.
- * To run this test: `atest FlickerTests:SwitchImeWindowsFromGestureNavTest`
+ * Test IME windows switching with 2-Buttons or gestural navigation. To run this test: `atest
+ * FlickerTests:SwitchImeWindowsFromGestureNavTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Presubmit
-open class SwitchImeWindowsFromGestureNavTest(
- testSpec: FlickerTestParameter
-) : BaseTest(testSpec) {
+open class SwitchImeWindowsFromGestureNavTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
private val testApp = SimpleAppHelper(instrumentation)
private val imeTestApp = ImeAppAutoFocusHelper(instrumentation, testSpec.startRotation)
@@ -66,22 +64,16 @@ open class SwitchImeWindowsFromGestureNavTest(
tapl.setExpectedRotationCheckEnabled(false)
this.setRotation(testSpec.startRotation)
testApp.launchViaIntent(wmHelper)
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(testApp)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
imeTestApp.launchViaIntent(wmHelper)
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(imeTestApp)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withFullScreenApp(imeTestApp).waitForAndVerify()
imeTestApp.openIME(wmHelper)
}
teardown {
tapl.goHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
testApp.exit(wmHelper)
imeTestApp.exit(wmHelper)
}
@@ -89,17 +81,13 @@ open class SwitchImeWindowsFromGestureNavTest(
// [Step1]: Swipe right from imeTestApp to testApp task
createTag(TAG_IME_VISIBLE)
tapl.launchedAppState.quickSwitchToPreviousApp()
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(testApp)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
createTag(TAG_IME_INVISIBLE)
}
transitions {
// [Step2]: Swipe left to back to imeTestApp task
tapl.launchedAppState.quickSwitchToPreviousAppSwipeLeft()
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(imeTestApp)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withFullScreenApp(imeTestApp).waitForAndVerify()
}
}
@@ -109,9 +97,7 @@ open class SwitchImeWindowsFromGestureNavTest(
override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
+ @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
/** {@inheritDoc} */
@Postsubmit
@@ -137,8 +123,7 @@ open class SwitchImeWindowsFromGestureNavTest(
/** {@inheritDoc} */
@Postsubmit
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
@Postsubmit
@@ -171,23 +156,15 @@ open class SwitchImeWindowsFromGestureNavTest(
@FlakyTest(bugId = 244414110)
@Test
open fun imeLayerIsVisibleWhenSwitchingToImeApp() {
- testSpec.assertLayersStart {
- isVisible(ComponentNameMatcher.IME)
- }
- testSpec.assertLayersTag(TAG_IME_VISIBLE) {
- isVisible(ComponentNameMatcher.IME)
- }
- testSpec.assertLayersEnd {
- isVisible(ComponentNameMatcher.IME)
- }
+ testSpec.assertLayersStart { isVisible(ComponentNameMatcher.IME) }
+ testSpec.assertLayersTag(TAG_IME_VISIBLE) { isVisible(ComponentNameMatcher.IME) }
+ testSpec.assertLayersEnd { isVisible(ComponentNameMatcher.IME) }
}
@Presubmit
@Test
fun imeLayerIsInvisibleWhenSwitchingToTestApp() {
- testSpec.assertLayersTag(TAG_IME_INVISIBLE) {
- isInvisible(ComponentNameMatcher.IME)
- }
+ testSpec.assertLayersTag(TAG_IME_INVISIBLE) { isInvisible(ComponentNameMatcher.IME) }
}
companion object {
@@ -196,9 +173,8 @@ open class SwitchImeWindowsFromGestureNavTest(
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- ),
+ supportedNavigationModes =
+ listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY),
supportedRotations = listOf(Surface.ROTATION_0)
)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt
index bd06279d53cd..80ab01624703 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/SwitchImeWindowsFromGestureNavTest_ShellTransit.kt
@@ -16,7 +16,6 @@
package com.android.server.wm.flicker.ime
-import android.platform.test.annotations.FlakyTest
import android.platform.test.annotations.Presubmit
import androidx.test.filters.RequiresDevice
import com.android.server.wm.flicker.FlickerParametersRunnerFactory
@@ -33,36 +32,35 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test IME windows switching with 2-Buttons or gestural navigation.
- * To run this test: `atest FlickerTests:SwitchImeWindowsFromGestureNavTest`
+ * Test IME windows switching with 2-Buttons or gestural navigation. To run this test: `atest
+ * FlickerTests:SwitchImeWindowsFromGestureNavTest`
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class SwitchImeWindowsFromGestureNavTest_ShellTransit(
- testSpec: FlickerTestParameter
-) : SwitchImeWindowsFromGestureNavTest(testSpec) {
+class SwitchImeWindowsFromGestureNavTest_ShellTransit(testSpec: FlickerTestParameter) :
+ SwitchImeWindowsFromGestureNavTest(testSpec) {
@Before
override fun before() {
Assume.assumeTrue(isShellTransitionsEnabled)
}
- @FlakyTest(bugId = 228012334)
+ @Presubmit
@Test
override fun entireScreenCovered() = super.entireScreenCovered()
- @FlakyTest(bugId = 228012334)
+ @Presubmit
@Test
override fun imeLayerIsVisibleWhenSwitchingToImeApp() =
super.imeLayerIsVisibleWhenSwitchingToImeApp()
- @FlakyTest(bugId = 228012334)
+ @Presubmit
@Test
override fun visibleLayersShownMoreThanOneConsecutiveEntry() =
super.visibleLayersShownMoreThanOneConsecutiveEntry()
- @FlakyTest(bugId = 228012334)
+ @Presubmit
@Test
override fun visibleWindowsShownMoreThanOneConsecutiveEntry() =
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
@@ -73,8 +71,8 @@ class SwitchImeWindowsFromGestureNavTest_ShellTransit(
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/**
- * Checks that [ComponentMatcher.NAV_BAR] window is visible and above the app windows at the start
- * and end of the WM trace
+ * Checks that [ComponentMatcher.NAV_BAR] window is visible and above the app windows at the
+ * start and end of the WM trace
*/
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
index 1e575e614e36..49bf86d0c266 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/ActivitiesTransitionTest.kt
@@ -40,15 +40,18 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:ActivitiesTransitionTest`
*
* Actions:
+ * ```
* Launch an app
* Launch a secondary activity within the app
* Close the secondary activity back to the initial one
- *
+ * ```
* Notes:
+ * ```
* 1. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -63,15 +66,11 @@ class ActivitiesTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSp
tapl.setExpectedRotation(testSpec.startRotation)
testApp.launchViaIntent(wmHelper)
}
- teardown {
- testApp.exit(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
transitions {
testApp.openSecondActivity(device, wmHelper)
tapl.pressBack()
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(testApp)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
}
}
@@ -81,9 +80,9 @@ class ActivitiesTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSp
override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
/**
- * Checks that the [ActivityOptions.LaunchNewActivity] activity is visible at
- * the start of the transition, that [ActivityOptions.SimpleActivity] becomes visible during
- * the transition, and that [ActivityOptions.LaunchNewActivity] is again visible at the end
+ * Checks that the [ActivityOptions.LaunchNewActivity] activity is visible at the start of the
+ * transition, that [ActivityOptions.SimpleActivity] becomes visible during the transition, and
+ * that [ActivityOptions.LaunchNewActivity] is again visible at the end
*/
@Presubmit
@Test
@@ -109,9 +108,7 @@ class ActivitiesTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSp
@Presubmit
@Test
fun launcherWindowNotOnTop() {
- testSpec.assertWm {
- this.isAppWindowNotOnTop(ComponentNameMatcher.LAUNCHER)
- }
+ testSpec.assertWm { this.isAppWindowNotOnTop(ComponentNameMatcher.LAUNCHER) }
}
/**
@@ -127,14 +124,13 @@ class ActivitiesTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSp
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt
index 480226fd86da..d0d7bbb42330 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest.kt
@@ -35,22 +35,21 @@ import org.junit.runners.Parameterized
*
* To run this test: `atest FlickerTests:OpenAppAfterCameraTest`
*
- * Notes:
- * Some default assertions are inherited [OpenAppTransition]
+ * Notes: Some default assertions are inherited [OpenAppTransition]
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenAppAfterCameraTest(
- testSpec: FlickerTestParameter
-) : OpenAppFromLauncherTransition(testSpec) {
+open class OpenAppAfterCameraTest(testSpec: FlickerTestParameter) :
+ OpenAppFromLauncherTransition(testSpec) {
@Before
open fun before() {
Assume.assumeFalse(isShellTransitionsEnabled)
}
- private val cameraApp = CameraAppHelper(instrumentation) /** {@inheritDoc} */
+ private val cameraApp = CameraAppHelper(instrumentation)
+ /** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
@@ -62,26 +61,21 @@ open class OpenAppAfterCameraTest(
// 2. Press home button (button nav mode) / swipe up to home (gesture nav mode)
tapl.goHome()
}
- teardown {
- testApp.exit(wmHelper)
- }
- transitions {
- testApp.launchViaIntent(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
+ transitions { testApp.launchViaIntent(wmHelper) }
}
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest_ShellTransit.kt
index 9e271061cc19..cb61e35eaedc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppAfterCameraTest_ShellTransit.kt
@@ -33,16 +33,14 @@ import org.junit.runners.Parameterized
*
* To run this test: `atest FlickerTests:OpenAppAfterCameraTest_ShellTransit`
*
- * Notes:
- * Some default assertions are inherited [OpenAppTransition]
+ * Notes: Some default assertions are inherited [OpenAppTransition]
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppAfterCameraTest_ShellTransit(
- testSpec: FlickerTestParameter
-) : OpenAppAfterCameraTest(testSpec) {
+class OpenAppAfterCameraTest_ShellTransit(testSpec: FlickerTestParameter) :
+ OpenAppAfterCameraTest(testSpec) {
@Before
override fun before() {
Assume.assumeFalse(isShellTransitionsEnabled)
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
index 8bc1b61f2fbd..7ccfeb7f6edd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdFromIcon.kt
@@ -37,24 +37,26 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:OpenAppColdFromIcon`
*
* Actions:
+ * ```
* Make sure no apps are running on the device
* Launch an app [testApp] by clicking it's icon on all apps and wait animation to complete
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [OpenAppTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class OpenAppColdFromIcon(
- testSpec: FlickerTestParameter
-) : OpenAppFromLauncherTransition(testSpec) {
+class OpenAppColdFromIcon(testSpec: FlickerTestParameter) :
+ OpenAppFromLauncherTransition(testSpec) {
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit
get() = {
@@ -69,21 +71,17 @@ class OpenAppColdFromIcon(
this.setRotation(testSpec.startRotation)
}
transitions {
- tapl.goHome()
+ tapl
+ .goHome()
.switchToAllApps()
.getAppIcon(testApp.launcherName)
.launch(testApp.`package`)
}
- teardown {
- testApp.exit(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
}
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowAsTopWindowAtEnd() =
- super.appWindowAsTopWindowAtEnd()
+ @Postsubmit @Test override fun appWindowAsTopWindowAtEnd() = super.appWindowAsTopWindowAtEnd()
/** {@inheritDoc} */
@Postsubmit
@@ -92,35 +90,22 @@ class OpenAppColdFromIcon(
super.appWindowReplacesLauncherAsTopWindow()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appLayerBecomesVisible() =
- super.appLayerBecomesVisible()
+ @Postsubmit @Test override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
+ @Postsubmit @Test override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
+ @Postsubmit @Test override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
+ @Postsubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
+ @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun focusChanges() = super.focusChanges()
+ @Postsubmit @Test override fun focusChanges() = super.focusChanges()
/** {@inheritDoc} */
@Postsubmit
@@ -150,8 +135,7 @@ class OpenAppColdFromIcon(
/** {@inheritDoc} */
@Postsubmit
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
@Postsubmit
@@ -177,22 +161,19 @@ class OpenAppColdFromIcon(
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowIsTopWindowAtEnd() = super.appWindowIsTopWindowAtEnd()
+ @Postsubmit @Test override fun appWindowIsTopWindowAtEnd() = super.appWindowIsTopWindowAtEnd()
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
index 0c169809b63f..7cd8526dc0f7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppColdTest.kt
@@ -38,25 +38,27 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:OpenAppColdTest`
*
* Actions:
+ * ```
* Make sure no apps are running on the device
* Launch an app [testApp] and wait animation to complete
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [OpenAppTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@FlickerServiceCompatible
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenAppColdTest(
- testSpec: FlickerTestParameter
-) : OpenAppFromLauncherTransition(testSpec) {
+open class OpenAppColdTest(testSpec: FlickerTestParameter) :
+ OpenAppFromLauncherTransition(testSpec) {
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit
get() = {
@@ -65,24 +67,17 @@ open class OpenAppColdTest(
removeAllTasksButHome()
this.setRotation(testSpec.startRotation)
}
- teardown {
- testApp.exit(wmHelper)
- }
- transitions {
- testApp.launchViaIntent(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
+ transitions { testApp.launchViaIntent(wmHelper) }
}
/** {@inheritDoc} */
@FlakyTest(bugId = 206753786)
@Test
- override fun navBarLayerPositionAtStartAndEnd() =
- super.navBarLayerPositionAtStartAndEnd()
+ override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Presubmit
- @Test
- override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
+ @Presubmit @Test override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
/** {@inheritDoc} */
@FlakyTest(bugId = 240238245)
@@ -94,14 +89,13 @@ open class OpenAppColdTest(
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
index bece406d5a96..23748bef96fd 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLauncherTransition.kt
@@ -22,32 +22,27 @@ import com.android.server.wm.flicker.replacesLayer
import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Test
-/**
- * Base class for app launch tests
- */
-abstract class OpenAppFromLauncherTransition(
- testSpec: FlickerTestParameter
-) : OpenAppTransition(testSpec) {
+/** Base class for app launch tests */
+abstract class OpenAppFromLauncherTransition(testSpec: FlickerTestParameter) :
+ OpenAppTransition(testSpec) {
- /**
- * Checks that the focus changes from the [ComponentMatcher.LAUNCHER] to [testApp]
- */
+ /** Checks that the focus changes from the [ComponentMatcher.LAUNCHER] to [testApp] */
@Presubmit
@Test
open fun focusChanges() {
- testSpec.assertEventLog {
- this.focusChanges("NexusLauncherActivity", testApp.`package`)
- }
+ testSpec.assertEventLog { this.focusChanges("NexusLauncherActivity", testApp.`package`) }
}
/**
- * Checks that [ComponentMatcher.LAUNCHER] layer is visible at the start of the transition,
- * and is replaced by [testApp], which remains visible until the end
+ * Checks that [ComponentMatcher.LAUNCHER] layer is visible at the start of the transition, and
+ * is replaced by [testApp], which remains visible until the end
*/
open fun appLayerReplacesLauncher() {
testSpec.replacesLayer(
- ComponentNameMatcher.LAUNCHER, testApp,
- ignoreEntriesWithRotationLayer = true, ignoreSnapshot = true,
+ ComponentNameMatcher.LAUNCHER,
+ testApp,
+ ignoreEntriesWithRotationLayer = true,
+ ignoreSnapshot = true,
ignoreSplashscreen = true
)
}
@@ -64,21 +59,15 @@ abstract class OpenAppFromLauncherTransition(
this.isAppWindowOnTop(ComponentNameMatcher.LAUNCHER)
.then()
.isAppWindowOnTop(
- testApp
- .or(ComponentNameMatcher.SNAPSHOT)
- .or(ComponentNameMatcher.SPLASH_SCREEN)
+ testApp.or(ComponentNameMatcher.SNAPSHOT).or(ComponentNameMatcher.SPLASH_SCREEN)
)
}
}
- /**
- * Checks that [testApp] window is the top window at the en dof the trace
- */
+ /** Checks that [testApp] window is the top window at the en dof the trace */
@Presubmit
@Test
open fun appWindowAsTopWindowAtEnd() {
- testSpec.assertWmEnd {
- this.isAppWindowOnTop(testApp)
- }
+ testSpec.assertWmEnd { this.isAppWindowOnTop(testApp) }
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
index a9972ce4610d..2469faeaaa66 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationCold.kt
@@ -54,18 +54,14 @@ open class OpenAppFromLockNotificationCold(testSpec: FlickerTestParameter) :
get() = {
// Needs to run at start of transition,
// so before the transition defined in super.transition
- transitions {
- device.wakeUp()
- }
+ transitions { device.wakeUp() }
super.transition(this)
// Needs to run at the end of the setup, so after the setup defined in super.transition
setup {
device.sleep()
- wmHelper.StateSyncBuilder()
- .withoutTopVisibleAppWindows()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
}
}
@@ -86,13 +82,9 @@ open class OpenAppFromLockNotificationCold(testSpec: FlickerTestParameter) :
override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
/** {@inheritDoc} */
- @Test
- @Ignore("Display is off at the start")
- override fun navBarLayerPositionAtStartAndEnd() { }
+ @Test @Ignore("Display is off at the start") override fun navBarLayerPositionAtStartAndEnd() {}
- /**
- * Checks the position of the [ComponentMatcher.NAV_BAR] at the end of the transition
- */
+ /** Checks the position of the [ComponentMatcher.NAV_BAR] at the end of the transition */
@Postsubmit
@Test
fun navBarLayerPositionAtEnd() {
@@ -103,15 +95,13 @@ open class OpenAppFromLockNotificationCold(testSpec: FlickerTestParameter) :
/** {@inheritDoc} */
@Test
@Ignore("Display is off at the start")
- override fun statusBarLayerPositionAtStartAndEnd() { }
+ override fun statusBarLayerPositionAtStartAndEnd() {}
/**
* Checks the position of the [ComponentMatcher.STATUS_BAR] at the start and end of the
* transition
*/
- @Postsubmit
- @Test
- fun statusBarLayerPositionEnd() = testSpec.statusBarLayerPositionAtEnd()
+ @Postsubmit @Test fun statusBarLayerPositionEnd() = testSpec.statusBarLayerPositionAtEnd()
/** {@inheritDoc} */
@Postsubmit
@@ -124,9 +114,7 @@ open class OpenAppFromLockNotificationCold(testSpec: FlickerTestParameter) :
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
+ @Postsubmit @Test override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
/** {@inheritDoc} */
@Postsubmit
@@ -134,9 +122,7 @@ open class OpenAppFromLockNotificationCold(testSpec: FlickerTestParameter) :
override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
+ @Postsubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
/** {@inheritDoc} */
@Postsubmit
@@ -151,23 +137,19 @@ open class OpenAppFromLockNotificationCold(testSpec: FlickerTestParameter) :
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowIsTopWindowAtEnd() =
- super.appWindowIsTopWindowAtEnd()
+ @Postsubmit @Test override fun appWindowIsTopWindowAtEnd() = super.appWindowIsTopWindowAtEnd()
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
index 950c54c84a1c..c26b665953da 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWarm.kt
@@ -58,49 +58,40 @@ open class OpenAppFromLockNotificationWarm(testSpec: FlickerTestParameter) :
get() = {
// Needs to run at start of transition,
// so before the transition defined in super.transition
- transitions {
- device.wakeUp()
- }
+ transitions { device.wakeUp() }
super.transition(this)
// Needs to run at the end of the setup, so after the setup defined in super.transition
setup {
device.sleep()
- wmHelper.StateSyncBuilder()
- .withoutTopVisibleAppWindows()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
}
}
/**
- * Checks that we start of with no top windows and then [testApp] becomes the first and
- * only top window of the transition, with snapshot or splash screen windows optionally showing
- * first.
+ * Checks that we start of with no top windows and then [testApp] becomes the first and only top
+ * window of the transition, with snapshot or splash screen windows optionally showing first.
*/
@Test
@Postsubmit
open fun appWindowBecomesFirstAndOnlyTopWindow() {
testSpec.assertWm {
this.hasNoVisibleAppWindow()
- .then()
- .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
- .then()
- .isAppWindowOnTop(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
- .then()
- .isAppWindowOnTop(testApp)
+ .then()
+ .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+ .then()
+ .isAppWindowOnTop(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
+ .then()
+ .isAppWindowOnTop(testApp)
}
}
- /**
- * Checks that the screen is locked at the start of the transition
- */
+ /** Checks that the screen is locked at the start of the transition */
@Test
@Postsubmit
fun screenLockedStart() {
- testSpec.assertWmStart {
- isKeyguardShowing()
- }
+ testSpec.assertWmStart { isKeyguardShowing() }
}
/** {@inheritDoc} */
@@ -117,11 +108,9 @@ open class OpenAppFromLockNotificationWarm(testSpec: FlickerTestParameter) :
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
- override fun navBarLayerPositionAtStartAndEnd() { }
+ override fun navBarLayerPositionAtStartAndEnd() {}
- /**
- * Checks the position of the [ComponentNameMatcher.NAV_BAR] at the end of the transition
- */
+ /** Checks the position of the [ComponentNameMatcher.NAV_BAR] at the end of the transition */
@Postsubmit
@Test
fun navBarLayerPositionAtEnd() {
@@ -132,40 +121,31 @@ open class OpenAppFromLockNotificationWarm(testSpec: FlickerTestParameter) :
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
- override fun statusBarLayerPositionAtStartAndEnd() { }
+ override fun statusBarLayerPositionAtStartAndEnd() {}
/**
* Checks the position of the [ComponentNameMatcher.STATUS_BAR] at the start and end of the
* transition
*/
- @Postsubmit
- @Test
- fun statusBarLayerPositionEnd() = testSpec.statusBarLayerPositionAtEnd()
+ @Postsubmit @Test fun statusBarLayerPositionEnd() = testSpec.statusBarLayerPositionAtEnd()
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
- override fun navBarLayerIsVisibleAtStartAndEnd() =
- super.navBarLayerIsVisibleAtStartAndEnd()
+ override fun navBarLayerIsVisibleAtStartAndEnd() = super.navBarLayerIsVisibleAtStartAndEnd()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- fun navBarLayerIsVisibleAtEnd() = testSpec.navBarLayerIsVisibleAtEnd()
+ @Postsubmit @Test fun navBarLayerIsVisibleAtEnd() = testSpec.navBarLayerIsVisibleAtEnd()
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts locked and app is full screen at the end")
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
- @Postsubmit
- @Test
- fun navBarWindowIsVisibleAtEnd() = testSpec.navBarWindowIsVisibleAtEnd()
+ @Postsubmit @Test fun navBarWindowIsVisibleAtEnd() = testSpec.navBarWindowIsVisibleAtEnd()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
+ @Postsubmit @Test override fun appLayerBecomesVisible() = super.appLayerBecomesVisible()
/** {@inheritDoc} */
@Postsubmit
@@ -173,14 +153,10 @@ open class OpenAppFromLockNotificationWarm(testSpec: FlickerTestParameter) :
override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
+ @Postsubmit @Test override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
+ @Postsubmit @Test override fun appWindowBecomesVisible() = super.appWindowBecomesVisible()
/** {@inheritDoc} */
@Postsubmit
@@ -195,10 +171,7 @@ open class OpenAppFromLockNotificationWarm(testSpec: FlickerTestParameter) :
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowIsTopWindowAtEnd() =
- super.appWindowIsTopWindowAtEnd()
+ @Postsubmit @Test override fun appWindowIsTopWindowAtEnd() = super.appWindowIsTopWindowAtEnd()
/** {@inheritDoc} */
@Presubmit
@@ -210,14 +183,13 @@ open class OpenAppFromLockNotificationWarm(testSpec: FlickerTestParameter) :
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
index c07989425074..0b4361ce8f2e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockNotificationWithLockOverlayApp.kt
@@ -33,8 +33,8 @@ import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
- * Test cold launching an app from a notification from the lock screen when there is an app
- * overlaid on the lock screen.
+ * Test cold launching an app from a notification from the lock screen when there is an app overlaid
+ * on the lock screen.
*
* To run this test: `atest FlickerTests:OpenAppFromLockNotificationWithLockOverlayApp`
*/
@@ -46,7 +46,7 @@ import org.junit.runners.Parameterized
class OpenAppFromLockNotificationWithLockOverlayApp(testSpec: FlickerTestParameter) :
OpenAppFromLockNotificationCold(testSpec) {
private val showWhenLockedApp: ShowWhenLockedAppHelper =
- ShowWhenLockedAppHelper(instrumentation)
+ ShowWhenLockedAppHelper(instrumentation)
// Although we are technically still locked here, the overlay app means we should open the
// notification shade as if we were unlocked.
@@ -61,19 +61,13 @@ class OpenAppFromLockNotificationWithLockOverlayApp(testSpec: FlickerTestParamet
// Launch an activity that is shown when the device is locked
showWhenLockedApp.launchViaIntent(wmHelper)
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(showWhenLockedApp)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withFullScreenApp(showWhenLockedApp).waitForAndVerify()
device.sleep()
- wmHelper.StateSyncBuilder()
- .withoutTopVisibleAppWindows()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
}
- teardown {
- showWhenLockedApp.exit(wmHelper)
- }
+ teardown { showWhenLockedApp.exit(wmHelper) }
}
@Test
@@ -81,10 +75,10 @@ class OpenAppFromLockNotificationWithLockOverlayApp(testSpec: FlickerTestParamet
fun showWhenLockedAppWindowBecomesVisible() {
testSpec.assertWm {
this.hasNoVisibleAppWindow()
- .then()
- .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
- .then()
- .isAppWindowOnTop(showWhenLockedApp)
+ .then()
+ .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+ .then()
+ .isAppWindowOnTop(showWhenLockedApp)
}
}
@@ -93,10 +87,10 @@ class OpenAppFromLockNotificationWithLockOverlayApp(testSpec: FlickerTestParamet
fun showWhenLockedAppLayerBecomesVisible() {
testSpec.assertLayers {
this.isInvisible(showWhenLockedApp)
- .then()
- .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
- .then()
- .isVisible(showWhenLockedApp)
+ .then()
+ .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+ .then()
+ .isVisible(showWhenLockedApp)
}
}
@@ -106,22 +100,19 @@ class OpenAppFromLockNotificationWithLockOverlayApp(testSpec: FlickerTestParamet
override fun entireScreenCovered() = super.entireScreenCovered()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
+ @Postsubmit @Test override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
index f574c9e12c96..3cc23909b603 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromLockTransition.kt
@@ -27,40 +27,26 @@ import org.junit.Assume
import org.junit.Ignore
import org.junit.Test
-/**
- * Base class for app launch tests from lock screen
- */
+/** Base class for app launch tests from lock screen */
abstract class OpenAppFromLockTransition(testSpec: FlickerTestParameter) :
OpenAppTransition(testSpec) {
- /**
- * Defines the transition used to run the test
- */
+ /** Defines the transition used to run the test */
override val transition: FlickerBuilder.() -> Unit = {
super.transition(this)
setup {
device.sleep()
- wmHelper.StateSyncBuilder()
- .withoutTopVisibleAppWindows()
- .waitForAndVerify()
- }
- teardown {
- testApp.exit(wmHelper)
- }
- transitions {
- testApp.launchViaIntent(wmHelper)
+ wmHelper.StateSyncBuilder().withoutTopVisibleAppWindows().waitForAndVerify()
}
+ teardown { testApp.exit(wmHelper) }
+ transitions { testApp.launchViaIntent(wmHelper) }
}
- /**
- * Check that we go from no focus to focus on the [testApp]
- */
+ /** Check that we go from no focus to focus on the [testApp] */
@Presubmit
@Test
open fun focusChanges() {
- testSpec.assertEventLog {
- this.focusChanges("", testApp.`package`)
- }
+ testSpec.assertEventLog { this.focusChanges("", testApp.`package`) }
}
/**
@@ -72,24 +58,20 @@ abstract class OpenAppFromLockTransition(testSpec: FlickerTestParameter) :
open fun appWindowBecomesFirstAndOnlyTopWindow() {
testSpec.assertWm {
this.hasNoVisibleAppWindow()
- .then()
- .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
- .then()
- .isAppWindowOnTop(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
- .then()
- .isAppWindowOnTop(testApp)
+ .then()
+ .isAppWindowOnTop(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+ .then()
+ .isAppWindowOnTop(ComponentNameMatcher.SPLASH_SCREEN, isOptional = true)
+ .then()
+ .isAppWindowOnTop(testApp)
}
}
- /**
- * Checks that the screen is locked at the start of the transition
- */
+ /** Checks that the screen is locked at the start of the transition */
@Presubmit
@Test
fun screenLockedStart() {
- testSpec.assertLayersStart {
- isEmpty()
- }
+ testSpec.assertLayersStart { isEmpty() }
}
/** {@inheritDoc} */
@@ -100,26 +82,24 @@ abstract class OpenAppFromLockTransition(testSpec: FlickerTestParameter) :
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
- override fun navBarLayerPositionAtStartAndEnd() { }
+ override fun navBarLayerPositionAtStartAndEnd() {}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
- override fun statusBarLayerPositionAtStartAndEnd() { }
+ override fun statusBarLayerPositionAtStartAndEnd() {}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
- override fun taskBarLayerIsVisibleAtStartAndEnd() { }
+ override fun taskBarLayerIsVisibleAtStartAndEnd() {}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
- override fun taskBarWindowIsAlwaysVisible() { }
+ override fun taskBarWindowIsAlwaysVisible() {}
- /**
- * Checks the position of the [ComponentMatcher.NAV_BAR] at the end of the transition
- */
+ /** Checks the position of the [ComponentMatcher.NAV_BAR] at the end of the transition */
@Presubmit
@Test
open fun navBarLayerPositionAtEnd() {
@@ -127,17 +107,13 @@ abstract class OpenAppFromLockTransition(testSpec: FlickerTestParameter) :
testSpec.navBarLayerPositionAtEnd()
}
- /**
- * Checks the position of the [ComponentMatcher.STATUS_BAR] at the end of the transition
- */
- @Presubmit
- @Test
- fun statusBarLayerPositionAtEnd() = testSpec.statusBarLayerPositionAtEnd()
+ /** Checks the position of the [ComponentMatcher.STATUS_BAR] at the end of the transition */
+ @Presubmit @Test fun statusBarLayerPositionAtEnd() = testSpec.statusBarLayerPositionAtEnd()
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
- override fun statusBarLayerIsVisibleAtStartAndEnd() { }
+ override fun statusBarLayerIsVisibleAtStartAndEnd() {}
/**
* Checks that the [ComponentMatcher.STATUS_BAR] layer is visible at the end of the trace
@@ -147,8 +123,6 @@ abstract class OpenAppFromLockTransition(testSpec: FlickerTestParameter) :
@Presubmit
@Test
fun statusBarLayerIsVisibleAtEnd() {
- testSpec.assertLayersEnd {
- this.isVisible(ComponentNameMatcher.STATUS_BAR)
- }
+ testSpec.assertLayersEnd { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
index dca3affc8f25..6802d7a5a372 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationCold.kt
@@ -39,9 +39,8 @@ import org.junit.runners.Parameterized
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Postsubmit
-open class OpenAppFromNotificationCold(
- testSpec: FlickerTestParameter
-) : OpenAppFromNotificationWarm(testSpec) {
+open class OpenAppFromNotificationCold(testSpec: FlickerTestParameter) :
+ OpenAppFromNotificationWarm(testSpec) {
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit
get() = {
@@ -60,14 +59,13 @@ open class OpenAppFromNotificationCold(
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
index e8a6a69cc50b..1ae0d5374c59 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromNotificationWarm.kt
@@ -54,9 +54,8 @@ import org.junit.runners.Parameterized
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
@Postsubmit
-open class OpenAppFromNotificationWarm(
- testSpec: FlickerTestParameter
-) : OpenAppTransition(testSpec) {
+open class OpenAppFromNotificationWarm(testSpec: FlickerTestParameter) :
+ OpenAppTransition(testSpec) {
override val testApp: NotificationAppHelper = NotificationAppHelper(instrumentation)
open val openingNotificationsFromLockScreen = false
@@ -68,14 +67,10 @@ open class OpenAppFromNotificationWarm(
device.wakeUpAndGoToHomeScreen()
this.setRotation(testSpec.startRotation)
testApp.launchViaIntent(wmHelper)
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(testApp)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
testApp.postNotification(wmHelper)
device.pressHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
}
transitions {
@@ -87,10 +82,10 @@ open class OpenAppFromNotificationWarm(
instrumentation.context.getSystemService(WindowManager::class.java)
?: error("Unable to connect to WindowManager service")
val metricInsets = wm.currentWindowMetrics.windowInsets
- val insets = metricInsets.getInsetsIgnoringVisibility(
- WindowInsets.Type.statusBars()
- or WindowInsets.Type.displayCutout()
- )
+ val insets =
+ metricInsets.getInsetsIgnoringVisibility(
+ WindowInsets.Type.statusBars() or WindowInsets.Type.displayCutout()
+ )
startY = insets.top + 100
endY = device.displayHeight / 2
@@ -104,23 +99,16 @@ open class OpenAppFromNotificationWarm(
instrumentation.uiAutomation.syncInputTransactions()
// Launch the activity by clicking the notification
- val notification = device.wait(
- Until.findObject(
- By.text("Flicker Test Notification")
- ), 2000L
- )
+ val notification =
+ device.wait(Until.findObject(By.text("Flicker Test Notification")), 2000L)
notification?.click() ?: error("Notification not found")
instrumentation.uiAutomation.syncInputTransactions()
// Wait for the app to launch
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(testApp)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
}
- teardown {
- testApp.exit(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
}
/** {@inheritDoc} */
@@ -137,8 +125,7 @@ open class OpenAppFromNotificationWarm(
/** {@inheritDoc} */
@Postsubmit
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
@Postsubmit
@@ -147,14 +134,10 @@ open class OpenAppFromNotificationWarm(
super.visibleLayersShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowBecomesVisible() = appWindowBecomesVisible_warmStart()
+ @Postsubmit @Test override fun appWindowBecomesVisible() = appWindowBecomesVisible_warmStart()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appLayerBecomesVisible() = appLayerBecomesVisible_warmStart()
+ @Postsubmit @Test override fun appLayerBecomesVisible() = appLayerBecomesVisible_warmStart()
/** {@inheritDoc} */
@Postsubmit
@@ -162,9 +145,7 @@ open class OpenAppFromNotificationWarm(
override fun statusBarWindowIsAlwaysVisible() = super.statusBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
+ @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
/** {@inheritDoc} */
@Postsubmit
@@ -183,33 +164,24 @@ open class OpenAppFromNotificationWarm(
super.visibleWindowsShownMoreThanOneConsecutiveEntry()
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun appWindowIsTopWindowAtEnd() =
- super.appWindowIsTopWindowAtEnd()
+ @Postsubmit @Test override fun appWindowIsTopWindowAtEnd() = super.appWindowIsTopWindowAtEnd()
@Postsubmit
@Test
open fun notificationAppWindowVisibleAtEnd() {
- testSpec.assertWmEnd {
- this.isAppWindowVisible(testApp)
- }
+ testSpec.assertWmEnd { this.isAppWindowVisible(testApp) }
}
@Postsubmit
@Test
open fun notificationAppWindowOnTopAtEnd() {
- testSpec.assertWmEnd {
- this.isAppWindowOnTop(testApp)
- }
+ testSpec.assertWmEnd { this.isAppWindowOnTop(testApp) }
}
@Postsubmit
@Test
open fun notificationAppLayerVisibleAtEnd() {
- testSpec.assertLayersEnd {
- this.isVisible(testApp)
- }
+ testSpec.assertLayersEnd { this.isVisible(testApp) }
}
/** {@inheritDoc} */
@@ -241,8 +213,7 @@ open class OpenAppFromNotificationWarm(
}
/**
- * Checks that the [ComponentNameMatcher.TASK_BAR] layer is visible at the end of the
- * transition
+ * Checks that the [ComponentNameMatcher.TASK_BAR] layer is visible at the end of the transition
*
* Note: Large screen only
*/
@@ -256,27 +227,24 @@ open class OpenAppFromNotificationWarm(
/** {@inheritDoc} */
@Test
@Ignore("Display is locked at the start")
- override fun taskBarWindowIsAlwaysVisible() =
- super.taskBarWindowIsAlwaysVisible()
+ override fun taskBarWindowIsAlwaysVisible() = super.taskBarWindowIsAlwaysVisible()
/** {@inheritDoc} */
@Test
@Ignore("Display is locked at the start")
- override fun taskBarLayerIsVisibleAtStartAndEnd() =
- super.taskBarLayerIsVisibleAtStartAndEnd()
+ override fun taskBarLayerIsVisibleAtStartAndEnd() = super.taskBarLayerIsVisibleAtStartAndEnd()
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 0bf57caefcda..fd8a38c3f6b7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -38,31 +38,31 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:OpenAppFromOverviewTest`
*
* Actions:
+ * ```
* Launch [testApp]
* Press recents
* Relaunch an app [testApp] by selecting it in the overview screen, and wait animation to
* complete (only this action is traced)
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [OpenAppTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@FlickerServiceCompatible
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class OpenAppFromOverviewTest(
- testSpec: FlickerTestParameter
-) : OpenAppFromLauncherTransition(testSpec) {
+open class OpenAppFromOverviewTest(testSpec: FlickerTestParameter) :
+ OpenAppFromLauncherTransition(testSpec) {
- /**
- * Defines the transition used to run the test
- */
+ /** Defines the transition used to run the test */
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
@@ -70,9 +70,7 @@ open class OpenAppFromOverviewTest(
tapl.setExpectedRotationCheckEnabled(false)
testApp.launchViaIntent(wmHelper)
tapl.goHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
// By default, launcher doesn't rotate on phones, but rotates on tablets
if (testSpec.isTablet) {
tapl.setExpectedRotation(testSpec.startRotation)
@@ -80,23 +78,17 @@ open class OpenAppFromOverviewTest(
tapl.setExpectedRotation(Surface.ROTATION_0)
}
tapl.workspace.switchToOverview()
- wmHelper.StateSyncBuilder()
- .withRecentsActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withRecentsActivityVisible().waitForAndVerify()
this.setRotation(testSpec.startRotation)
}
transitions {
tapl.overview.currentTask.open()
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(testApp)
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withFullScreenApp(testApp).waitForAndVerify()
}
}
/** {@inheritDoc} */
- @Presubmit
- @Test
- override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
+ @Presubmit @Test override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
/** {@inheritDoc} */
@FlakyTest
@@ -117,14 +109,13 @@ open class OpenAppFromOverviewTest(
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
index 11f3cced5b4d..559728739111 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppNonResizeableTest.kt
@@ -45,16 +45,19 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:OpenAppNonResizeableTest`
*
* Actions:
+ * ```
* Lock the device.
* Launch an app on top of the lock screen [testApp] and wait animation to complete
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [OpenAppTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@FlickerServiceCompatible
@@ -80,15 +83,11 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) :
}
}
- /**
- * Checks if [testApp] is visible at the end of the transition
- */
+ /** Checks if [testApp] is visible at the end of the transition */
@Presubmit
@Test
fun appWindowBecomesVisibleAtEnd() {
- testSpec.assertWmEnd {
- this.isAppWindowVisible(testApp)
- }
+ testSpec.assertWmEnd { this.isAppWindowVisible(testApp) }
}
/**
@@ -114,9 +113,7 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) :
@Test
fun taskBarLayerIsVisibleAtEnd() {
Assume.assumeTrue(testSpec.isTablet)
- testSpec.assertLayersEnd {
- this.isVisible(ComponentNameMatcher.TASK_BAR)
- }
+ testSpec.assertLayersEnd { this.isVisible(ComponentNameMatcher.TASK_BAR) }
}
/**
@@ -127,59 +124,43 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) :
@Presubmit
@Test
override fun statusBarLayerIsVisibleAtStartAndEnd() {
- testSpec.assertLayersEnd {
- this.isVisible(ComponentNameMatcher.STATUS_BAR)
- }
+ testSpec.assertLayersEnd { this.isVisible(ComponentNameMatcher.STATUS_BAR) }
}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
- override fun taskBarLayerIsVisibleAtStartAndEnd() {
- }
+ override fun taskBarLayerIsVisibleAtStartAndEnd() {}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
- override fun navBarLayerIsVisibleAtStartAndEnd() {
- }
+ override fun navBarLayerIsVisibleAtStartAndEnd() {}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
- override fun taskBarWindowIsAlwaysVisible() {
- }
+ override fun taskBarWindowIsAlwaysVisible() {}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
- override fun navBarWindowIsAlwaysVisible() {
- }
+ override fun navBarWindowIsAlwaysVisible() {}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. Display starts off and app is full screen at the end")
- override fun statusBarWindowIsAlwaysVisible() {
- }
+ override fun statusBarWindowIsAlwaysVisible() {}
- /**
- * Checks the position of the [ComponentMatcher.STATUS_BAR] at the end of the
- * transition
- */
- @Presubmit
- @Test
- fun statusBarLayerPositionEnd() = testSpec.statusBarLayerPositionAtEnd()
+ /** Checks the position of the [ComponentMatcher.STATUS_BAR] at the end of the transition */
+ @Presubmit @Test fun statusBarLayerPositionEnd() = testSpec.statusBarLayerPositionAtEnd()
- /**
- * Checks the [ComponentMatcher.NAV_BAR] is visible at the end of the transition
- */
+ /** Checks the [ComponentMatcher.NAV_BAR] is visible at the end of the transition */
@Postsubmit
@Test
fun navBarLayerIsVisibleAtEnd() {
Assume.assumeFalse(testSpec.isTablet)
- testSpec.assertLayersEnd {
- this.isVisible(ComponentNameMatcher.NAV_BAR)
- }
+ testSpec.assertLayersEnd { this.isVisible(ComponentNameMatcher.NAV_BAR) }
}
/** {@inheritDoc} */
@@ -205,9 +186,7 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) :
}
/** {@inheritDoc} */
- @FlakyTest
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
+ @FlakyTest @Test override fun entireScreenCovered() = super.entireScreenCovered()
@FlakyTest(bugId = 218470989)
@Test
@@ -216,23 +195,22 @@ open class OpenAppNonResizeableTest(testSpec: FlickerTestParameter) :
@FlakyTest(bugId = 227143265)
@Test
- override fun appWindowBecomesTopWindow() =
- super.appWindowBecomesTopWindow()
+ override fun appWindowBecomesTopWindow() = super.appWindowBecomesTopWindow()
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
- supportedNavigationModes =
- listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY),
+ supportedNavigationModes =
+ listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY),
supportedRotations = listOf(Surface.ROTATION_0)
)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
index face7da6f623..4fd251aefffc 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppTransition.kt
@@ -27,9 +27,7 @@ import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Test
-/**
- * Base class for app launch tests
- */
+/** Base class for app launch tests */
abstract class OpenAppTransition(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
protected open val testApp: StandardAppHelper = SimpleAppHelper(instrumentation)
@@ -40,14 +38,12 @@ abstract class OpenAppTransition(testSpec: FlickerTestParameter) : BaseTest(test
device.wakeUpAndGoToHomeScreen()
this.setRotation(testSpec.startRotation)
}
- teardown {
- testApp.exit(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
}
/**
- * Checks that the [testApp] layer doesn't exist or is invisible at the start of the
- * transition, but is created and/or becomes visible during the transition.
+ * Checks that the [testApp] layer doesn't exist or is invisible at the start of the transition,
+ * but is created and/or becomes visible during the transition.
*/
@Presubmit
@Test
@@ -85,12 +81,10 @@ abstract class OpenAppTransition(testSpec: FlickerTestParameter) : BaseTest(test
* Checks that the [testApp] window doesn't exist at the start of the transition, that it is
* created (invisible - optional) and becomes visible during the transition
*
- * The `isAppWindowInvisible` step is optional because we log once per frame, upon logging,
- * the window may be visible or not depending on what was processed until that moment.
+ * The `isAppWindowInvisible` step is optional because we log once per frame, upon logging, the
+ * window may be visible or not depending on what was processed until that moment.
*/
- @Presubmit
- @Test
- open fun appWindowBecomesVisible() = appWindowBecomesVisible_coldStart()
+ @Presubmit @Test open fun appWindowBecomesVisible() = appWindowBecomesVisible_coldStart()
protected fun appWindowBecomesVisible_coldStart() {
testSpec.assertWm {
@@ -125,9 +119,7 @@ abstract class OpenAppTransition(testSpec: FlickerTestParameter) : BaseTest(test
this.isAppWindowNotOnTop(testApp)
.then()
.isAppWindowOnTop(
- testApp
- .or(ComponentNameMatcher.SNAPSHOT)
- .or(ComponentNameMatcher.SPLASH_SCREEN)
+ testApp.or(ComponentNameMatcher.SNAPSHOT).or(ComponentNameMatcher.SPLASH_SCREEN)
)
}
}
@@ -139,8 +131,6 @@ abstract class OpenAppTransition(testSpec: FlickerTestParameter) : BaseTest(test
@Presubmit
@Test
open fun appWindowIsTopWindowAtEnd() {
- testSpec.assertWmEnd {
- this.isAppWindowOnTop(testApp)
- }
+ testSpec.assertWmEnd { this.isAppWindowOnTop(testApp) }
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
index f7fb9e339e59..03741c8f968c 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppWarmTest.kt
@@ -37,17 +37,20 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:OpenAppWarmTest`
*
* Actions:
+ * ```
* Launch [testApp]
* Press home
* Relaunch an app [testApp] and wait animation to complete (only this action is traced)
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [OpenAppTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@FlickerServiceCompatible
@@ -56,9 +59,7 @@ import org.junit.runners.Parameterized
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
open class OpenAppWarmTest(testSpec: FlickerTestParameter) :
OpenAppFromLauncherTransition(testSpec) {
- /**
- * Defines the transition used to run the test
- */
+ /** Defines the transition used to run the test */
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
@@ -66,17 +67,11 @@ open class OpenAppWarmTest(testSpec: FlickerTestParameter) :
tapl.setExpectedRotationCheckEnabled(false)
testApp.launchViaIntent(wmHelper)
tapl.goHome()
- wmHelper.StateSyncBuilder()
- .withHomeActivityVisible()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withHomeActivityVisible().waitForAndVerify()
this.setRotation(testSpec.startRotation)
}
- teardown {
- testApp.exit(wmHelper)
- }
- transitions {
- testApp.launchViaIntent(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
+ transitions { testApp.launchViaIntent(wmHelper) }
}
/** {@inheritDoc} */
@@ -85,9 +80,7 @@ open class OpenAppWarmTest(testSpec: FlickerTestParameter) :
override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
- @Presubmit
- @Test
- override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
+ @Presubmit @Test override fun appLayerReplacesLauncher() = super.appLayerReplacesLauncher()
/** {@inheritDoc} */
@Presubmit
@@ -103,14 +96,13 @@ open class OpenAppWarmTest(testSpec: FlickerTestParameter) :
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigNonRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
index 18cc55b80198..bc2fe469a010 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OverrideTaskTransitionTest.kt
@@ -49,7 +49,9 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:OverrideTaskTransitionTest`
*
* Actions:
+ * ```
* Launches SimpleActivity with alpha_2000ms animation
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -70,16 +72,17 @@ class OverrideTaskTransitionTest(val testSpec: FlickerTestParameter) {
}
transitions {
instrumentation.context.startActivity(
- testApp.openAppIntent, createCustomTaskAnimation())
- wmHelper.StateSyncBuilder()
- .add(WindowManagerConditionsFactory.isWMStateComplete())
- .withAppTransitionIdle()
- .withWindowSurfaceAppeared(testApp)
- .waitForAndVerify()
- }
- teardown {
- testApp.exit()
+ testApp.openAppIntent,
+ createCustomTaskAnimation()
+ )
+ wmHelper
+ .StateSyncBuilder()
+ .add(WindowManagerConditionsFactory.isWMStateComplete())
+ .withAppTransitionIdle()
+ .withWindowSurfaceAppeared(testApp)
+ .waitForAndVerify()
}
+ teardown { testApp.exit() }
}
}
@@ -98,16 +101,22 @@ class OverrideTaskTransitionTest(val testSpec: FlickerTestParameter) {
}
private fun createCustomTaskAnimation(): Bundle {
- return android.app.ActivityOptions.makeCustomTaskAnimation(instrumentation.context,
- R.anim.show_2000ms, 0, Handler.getMain(), null, null).toBundle()
+ return android.app.ActivityOptions.makeCustomTaskAnimation(
+ instrumentation.context,
+ R.anim.show_2000ms,
+ 0,
+ Handler.getMain(),
+ null,
+ null
+ )
+ .toBundle()
}
companion object {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
index a43833014308..06486ca85292 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/TaskTransitionTest.kt
@@ -45,9 +45,11 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:ActivitiesTransitionTest`
*
* Actions:
+ * ```
* Launch the NewTaskLauncherApp [mTestApp]
* Open a new task (SimpleActivity) from the NewTaskLauncherApp [mTestApp]
* Go back to the NewTaskLauncherApp [mTestApp]
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -61,36 +63,28 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit = {
- setup {
- testApp.launchViaIntent(wmHelper)
- }
- teardown {
- testApp.exit(wmHelper)
- }
+ setup { testApp.launchViaIntent(wmHelper) }
+ teardown { testApp.exit(wmHelper) }
transitions {
testApp.openNewTask(device, wmHelper)
tapl.pressBack()
- wmHelper.StateSyncBuilder()
- .withAppTransitionIdle()
- .waitForAndVerify()
+ wmHelper.StateSyncBuilder().withAppTransitionIdle().waitForAndVerify()
}
}
/**
- * Checks that the [wallpaper] window is never visible when performing task transitions.
- * A solid color background should be shown instead.
+ * Checks that the [wallpaper] window is never visible when performing task transitions. A solid
+ * color background should be shown instead.
*/
@Postsubmit
@Test
fun wallpaperWindowIsNeverVisible() {
- testSpec.assertWm {
- this.isNonAppWindowInvisible(wallpaper)
- }
+ testSpec.assertWm { this.isNonAppWindowInvisible(wallpaper) }
}
/**
- * Checks that the [wallpaper] layer is never visible when performing task transitions.
- * A solid color background should be shown instead.
+ * Checks that the [wallpaper] layer is never visible when performing task transitions. A solid
+ * color background should be shown instead.
*/
@Postsubmit
@Test
@@ -103,33 +97,25 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
/**
* Check that the [ComponentNameMatcher.LAUNCHER] window is never visible when performing task
- * transitions.
- * A solid color background should be shown above it.
+ * transitions. A solid color background should be shown above it.
*/
@Postsubmit
@Test
fun launcherWindowIsNeverVisible() {
- testSpec.assertWm {
- this.isAppWindowInvisible(ComponentNameMatcher.LAUNCHER)
- }
+ testSpec.assertWm { this.isAppWindowInvisible(ComponentNameMatcher.LAUNCHER) }
}
/**
* Checks that the [ComponentNameMatcher.LAUNCHER] layer is never visible when performing task
- * transitions.
- * A solid color background should be shown above it.
+ * transitions. A solid color background should be shown above it.
*/
@Postsubmit
@Test
fun launcherLayerIsNeverVisible() {
- testSpec.assertLayers {
- this.isInvisible(ComponentNameMatcher.LAUNCHER)
- }
+ testSpec.assertLayers { this.isInvisible(ComponentNameMatcher.LAUNCHER) }
}
- /**
- * Checks that a color background is visible while the task transition is occurring.
- */
+ /** Checks that a color background is visible while the task transition is occurring. */
@Postsubmit
@Test
fun colorLayerIsVisibleDuringTransition() {
@@ -138,8 +124,8 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
testSpec.assertLayers {
this.invoke("LAUNCH_NEW_TASK_ACTIVITY coversExactly displayBounds") {
- it.visibleRegion(LAUNCH_NEW_TASK_ACTIVITY).coversExactly(displayBounds)
- }
+ it.visibleRegion(LAUNCH_NEW_TASK_ACTIVITY).coversExactly(displayBounds)
+ }
.isInvisible(bgColorLayer)
.then()
// Transitioning
@@ -163,8 +149,8 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
}
/**
- * Checks that we start with the LaunchNewTask activity on top and then open up
- * the SimpleActivity and then go back to the LaunchNewTask activity.
+ * Checks that we start with the LaunchNewTask activity on top and then open up the
+ * SimpleActivity and then go back to the LaunchNewTask activity.
*/
@Postsubmit
@Test
@@ -183,9 +169,7 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
}
/** {@inheritDoc} */
- @Postsubmit
- @Test
- override fun entireScreenCovered() = super.entireScreenCovered()
+ @Postsubmit @Test override fun entireScreenCovered() = super.entireScreenCovered()
/** {@inheritDoc} */
@Postsubmit
@@ -206,8 +190,7 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
/** {@inheritDoc} */
@Postsubmit
@Test
- override fun statusBarLayerPositionAtStartAndEnd() =
- super.statusBarLayerPositionAtStartAndEnd()
+ override fun statusBarLayerPositionAtStartAndEnd() = super.statusBarLayerPositionAtStartAndEnd()
/** {@inheritDoc} */
@Postsubmit
@@ -255,8 +238,7 @@ class TaskTransitionTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigNonRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
index 87ae8435deab..3f1a4180409f 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest.kt
@@ -45,18 +45,17 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsBackTest`
*
* Actions:
+ * ```
* Launch an app [testApp1]
* Launch another app [testApp2]
* Swipe right from the bottom of the screen to quick switch back to the first app [testApp1]
- *
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class QuickSwitchBetweenTwoAppsBackTest(
- testSpec: FlickerTestParameter
-) : BaseTest(testSpec) {
+open class QuickSwitchBetweenTwoAppsBackTest(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
private val testApp1 = SimpleAppHelper(instrumentation)
private val testApp2 = NonResizeableAppHelper(instrumentation)
@@ -71,12 +70,13 @@ open class QuickSwitchBetweenTwoAppsBackTest(
tapl.setExpectedRotation(testSpec.startRotation)
testApp1.launchViaIntent(wmHelper)
testApp2.launchViaIntent(wmHelper)
- startDisplayBounds = wmHelper.currentState.layerState
- .physicalDisplayBounds ?: error("Display not found")
+ startDisplayBounds =
+ wmHelper.currentState.layerState.physicalDisplayBounds ?: error("Display not found")
}
transitions {
tapl.launchedAppState.quickSwitchToPreviousApp()
- wmHelper.StateSyncBuilder()
+ wmHelper
+ .StateSyncBuilder()
.withFullScreenApp(testApp1)
.withNavOrTaskBarVisible()
.withStatusBarVisible()
@@ -96,9 +96,7 @@ open class QuickSwitchBetweenTwoAppsBackTest(
@Presubmit
@Test
open fun startsWithApp2WindowsCoverFullScreen() {
- testSpec.assertWmStart {
- this.visibleRegion(testApp2).coversExactly(startDisplayBounds)
- }
+ testSpec.assertWmStart { this.visibleRegion(testApp2).coversExactly(startDisplayBounds) }
}
/**
@@ -113,15 +111,11 @@ open class QuickSwitchBetweenTwoAppsBackTest(
}
}
- /**
- * Checks that the transition starts with [testApp2] being the top window.
- */
+ /** Checks that the transition starts with [testApp2] being the top window. */
@Presubmit
@Test
open fun startsWithApp2WindowBeingOnTop() {
- testSpec.assertWmStart {
- this.isAppWindowOnTop(testApp2)
- }
+ testSpec.assertWmStart { this.isAppWindowOnTop(testApp2) }
}
/**
@@ -131,21 +125,17 @@ open class QuickSwitchBetweenTwoAppsBackTest(
@Presubmit
@Test
open fun endsWithApp1WindowsCoveringFullScreen() {
- testSpec.assertWmEnd {
- this.visibleRegion(testApp1).coversExactly(startDisplayBounds)
- }
+ testSpec.assertWmEnd { this.visibleRegion(testApp1).coversExactly(startDisplayBounds) }
}
/**
- * Checks that [testApp1] layers fill the entire screen (i.e. is "fullscreen") at the end of
- * the transition once we have fully quick switched from [testApp2] back to the [testApp1].
+ * Checks that [testApp1] layers fill the entire screen (i.e. is "fullscreen") at the end of the
+ * transition once we have fully quick switched from [testApp2] back to the [testApp1].
*/
@Presubmit
@Test
fun endsWithApp1LayersCoveringFullScreen() {
- testSpec.assertLayersEnd {
- this.visibleRegion(testApp1).coversExactly(startDisplayBounds)
- }
+ testSpec.assertLayersEnd { this.visibleRegion(testApp1).coversExactly(startDisplayBounds) }
}
/**
@@ -155,14 +145,12 @@ open class QuickSwitchBetweenTwoAppsBackTest(
@Presubmit
@Test
open fun endsWithApp1BeingOnTop() {
- testSpec.assertWmEnd {
- this.isAppWindowOnTop(testApp1)
- }
+ testSpec.assertWmEnd { this.isAppWindowOnTop(testApp1) }
}
/**
- * Checks that [testApp1]'s window starts off invisible and becomes visible at some point
- * before the end of the transition and then stays visible until the end of the transition.
+ * Checks that [testApp1]'s window starts off invisible and becomes visible at some point before
+ * the end of the transition and then stays visible until the end of the transition.
*/
@Presubmit
@Test
@@ -177,45 +165,35 @@ open class QuickSwitchBetweenTwoAppsBackTest(
}
/**
- * Checks that [testApp1]'s layer starts off invisible and becomes visible at some point
- * before the end of the transition and then stays visible until the end of the transition.
+ * Checks that [testApp1]'s layer starts off invisible and becomes visible at some point before
+ * the end of the transition and then stays visible until the end of the transition.
*/
@Presubmit
@Test
open fun app1LayerBecomesAndStaysVisible() {
- testSpec.assertLayers {
- this.isInvisible(testApp1)
- .then()
- .isVisible(testApp1)
- }
+ testSpec.assertLayers { this.isInvisible(testApp1).then().isVisible(testApp1) }
}
/**
- * Checks that [testApp2]'s window starts off visible and becomes invisible at some point
- * before the end of the transition and then stays invisible until the end of the transition.
+ * Checks that [testApp2]'s window starts off visible and becomes invisible at some point before
+ * the end of the transition and then stays invisible until the end of the transition.
*/
@Presubmit
@Test
open fun app2WindowBecomesAndStaysInvisible() {
testSpec.assertWm {
- this.isAppWindowVisible(testApp2)
- .then()
- .isAppWindowInvisible(testApp2)
+ this.isAppWindowVisible(testApp2).then().isAppWindowInvisible(testApp2)
}
}
/**
- * Checks that [testApp2]'s layer starts off visible and becomes invisible at some point
- * before the end of the transition and then stays invisible until the end of the transition.
+ * Checks that [testApp2]'s layer starts off visible and becomes invisible at some point before
+ * the end of the transition and then stays invisible until the end of the transition.
*/
@Presubmit
@Test
open fun app2LayerBecomesAndStaysInvisible() {
- testSpec.assertLayers {
- this.isVisible(testApp2)
- .then()
- .isInvisible(testApp2)
- }
+ testSpec.assertLayers { this.isVisible(testApp2).then().isInvisible(testApp2) }
}
/**
@@ -274,9 +252,8 @@ open class QuickSwitchBetweenTwoAppsBackTest(
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
.getConfigNonRotationTests(
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- ),
+ supportedNavigationModes =
+ listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY),
supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90)
)
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
index 21652d922feb..7a1350e5bbfa 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsBackTest_ShellTransit.kt
@@ -38,18 +38,18 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsBackTest`
*
* Actions:
+ * ```
* Launch an app [testApp1]
* Launch another app [testApp2]
* Swipe right from the bottom of the screen to quick switch back to the first app [testApp1]
- *
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class QuickSwitchBetweenTwoAppsBackTest_ShellTransit(
- testSpec: FlickerTestParameter
-) : QuickSwitchBetweenTwoAppsBackTest(testSpec) {
+open class QuickSwitchBetweenTwoAppsBackTest_ShellTransit(testSpec: FlickerTestParameter) :
+ QuickSwitchBetweenTwoAppsBackTest(testSpec) {
@Before
override fun before() {
Assume.assumeTrue(isShellTransitionsEnabled)
@@ -61,8 +61,8 @@ open class QuickSwitchBetweenTwoAppsBackTest_ShellTransit(
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/**
- * Checks that [ComponentMatcher.NAV_BAR] window is visible and above the app windows at the start
- * and end of the WM trace
+ * Checks that [ComponentMatcher.NAV_BAR] window is visible and above the app windows at the
+ * start and end of the WM trace
*/
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
index 64259105411a..0a21044f6dda 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest.kt
@@ -45,18 +45,19 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsForwardTest`
*
* Actions:
+ * ```
* Launch an app [testApp1]
* Launch another app [testApp2]
* Swipe right from the bottom of the screen to quick switch back to the first app [testApp1]
* Swipe left from the bottom of the screen to quick switch forward to the second app [testApp2]
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class QuickSwitchBetweenTwoAppsForwardTest(
- testSpec: FlickerTestParameter
-) : BaseTest(testSpec) {
+open class QuickSwitchBetweenTwoAppsForwardTest(testSpec: FlickerTestParameter) :
+ BaseTest(testSpec) {
private val testApp1 = SimpleAppHelper(instrumentation)
private val testApp2 = NonResizeableAppHelper(instrumentation)
@@ -68,22 +69,24 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit = {
setup {
- tapl.setExpectedRotation(testSpec.startRotation)
+ tapl.setExpectedRotation(testSpec.startRotation)
- testApp1.launchViaIntent(wmHelper)
- testApp2.launchViaIntent(wmHelper)
- tapl.launchedAppState.quickSwitchToPreviousApp()
- wmHelper.StateSyncBuilder()
- .withFullScreenApp(testApp1)
- .withNavOrTaskBarVisible()
- .withStatusBarVisible()
- .waitForAndVerify()
- startDisplayBounds = wmHelper.currentState.layerState
- .physicalDisplayBounds ?: error("Display not found")
+ testApp1.launchViaIntent(wmHelper)
+ testApp2.launchViaIntent(wmHelper)
+ tapl.launchedAppState.quickSwitchToPreviousApp()
+ wmHelper
+ .StateSyncBuilder()
+ .withFullScreenApp(testApp1)
+ .withNavOrTaskBarVisible()
+ .withStatusBarVisible()
+ .waitForAndVerify()
+ startDisplayBounds =
+ wmHelper.currentState.layerState.physicalDisplayBounds ?: error("Display not found")
}
transitions {
tapl.launchedAppState.quickSwitchToPreviousAppSwipeLeft()
- wmHelper.StateSyncBuilder()
+ wmHelper
+ .StateSyncBuilder()
.withFullScreenApp(testApp2)
.withNavOrTaskBarVisible()
.withStatusBarVisible()
@@ -121,15 +124,11 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
}
}
- /**
- * Checks that the transition starts with [testApp1] being the top window.
- */
+ /** Checks that the transition starts with [testApp1] being the top window. */
@Presubmit
@Test
open fun startsWithApp1WindowBeingOnTop() {
- testSpec.assertWmStart {
- this.isAppWindowOnTop(testApp1)
- }
+ testSpec.assertWmStart { this.isAppWindowOnTop(testApp1) }
}
/**
@@ -139,9 +138,7 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
@Presubmit
@Test
open fun endsWithApp2WindowsCoveringFullScreen() {
- testSpec.assertWmEnd {
- this.visibleRegion(testApp2).coversExactly(startDisplayBounds)
- }
+ testSpec.assertWmEnd { this.visibleRegion(testApp2).coversExactly(startDisplayBounds) }
}
/**
@@ -164,9 +161,7 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
@Presubmit
@Test
open fun endsWithApp2BeingOnTop() {
- testSpec.assertWmEnd {
- this.isAppWindowOnTop(testApp2)
- }
+ testSpec.assertWmEnd { this.isAppWindowOnTop(testApp2) }
}
/**
@@ -178,10 +173,10 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
open fun app2WindowBecomesAndStaysVisible() {
testSpec.assertWm {
this.isAppWindowInvisible(testApp2)
- .then()
- .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
- .then()
- .isAppWindowVisible(testApp2)
+ .then()
+ .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+ .then()
+ .isAppWindowVisible(testApp2)
}
}
@@ -192,11 +187,7 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
@Presubmit
@Test
open fun app2LayerBecomesAndStaysVisible() {
- testSpec.assertLayers {
- this.isInvisible(testApp2)
- .then()
- .isVisible(testApp2)
- }
+ testSpec.assertLayers { this.isInvisible(testApp2).then().isVisible(testApp2) }
}
/**
@@ -207,9 +198,7 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
@Test
open fun app1WindowBecomesAndStaysInvisible() {
testSpec.assertWm {
- this.isAppWindowVisible(testApp1)
- .then()
- .isAppWindowInvisible(testApp1)
+ this.isAppWindowVisible(testApp1).then().isAppWindowInvisible(testApp1)
}
}
@@ -220,11 +209,7 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
@Presubmit
@Test
open fun app1LayerBecomesAndStaysInvisible() {
- testSpec.assertLayers {
- this.isVisible(testApp1)
- .then()
- .isInvisible(testApp1)
- }
+ testSpec.assertLayers { this.isVisible(testApp1).then().isInvisible(testApp1) }
}
/**
@@ -237,12 +222,12 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
open fun app2WindowIsVisibleOnceApp1WindowIsInvisible() {
testSpec.assertWm {
this.isAppWindowVisible(testApp1)
- .then()
- .isAppWindowVisible(ComponentNameMatcher.LAUNCHER, isOptional = true)
- .then()
- .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
- .then()
- .isAppWindowVisible(testApp2)
+ .then()
+ .isAppWindowVisible(ComponentNameMatcher.LAUNCHER, isOptional = true)
+ .then()
+ .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+ .then()
+ .isAppWindowVisible(testApp2)
}
}
@@ -256,12 +241,12 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
open fun app2LayerIsVisibleOnceApp1LayerIsInvisible() {
testSpec.assertLayers {
this.isVisible(testApp1)
- .then()
- .isVisible(ComponentNameMatcher.LAUNCHER, isOptional = true)
- .then()
- .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
- .then()
- .isVisible(testApp2)
+ .then()
+ .isVisible(ComponentNameMatcher.LAUNCHER, isOptional = true)
+ .then()
+ .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+ .then()
+ .isVisible(testApp2)
}
}
@@ -281,12 +266,11 @@ open class QuickSwitchBetweenTwoAppsForwardTest(
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- ),
- supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90)
- )
+ .getConfigNonRotationTests(
+ supportedNavigationModes =
+ listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY),
+ supportedRotations = listOf(Surface.ROTATION_0, Surface.ROTATION_90)
+ )
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
index 2f72fad23942..03647c9801c7 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchBetweenTwoAppsForwardTest_ShellTransit.kt
@@ -38,18 +38,19 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:QuickSwitchBetweenTwoAppsForwardTest`
*
* Actions:
+ * ```
* Launch an app [testApp1]
* Launch another app [testApp2]
* Swipe right from the bottom of the screen to quick switch back to the first app [testApp1]
* Swipe left from the bottom of the screen to quick switch forward to the second app [testApp2]
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class QuickSwitchBetweenTwoAppsForwardTest_ShellTransit(
- testSpec: FlickerTestParameter
-) : QuickSwitchBetweenTwoAppsForwardTest(testSpec) {
+open class QuickSwitchBetweenTwoAppsForwardTest_ShellTransit(testSpec: FlickerTestParameter) :
+ QuickSwitchBetweenTwoAppsForwardTest(testSpec) {
@Before
override fun before() {
Assume.assumeTrue(isShellTransitionsEnabled)
@@ -61,8 +62,8 @@ open class QuickSwitchBetweenTwoAppsForwardTest_ShellTransit(
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/**
- * Checks that [ComponentMatcher.NAV_BAR] window is visible and above the app windows at the start
- * and end of the WM trace
+ * Checks that [ComponentMatcher.NAV_BAR] window is visible and above the app windows at the
+ * start and end of the WM trace
*/
@Presubmit
@Test
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
index 702c2cf0ace6..3cb985a925b1 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/quickswitch/QuickSwitchFromLauncherTest.kt
@@ -45,10 +45,11 @@ import org.junit.runners.Parameterized
* To run this test: `atest FlickerTests:QuickSwitchFromLauncherTest`
*
* Actions:
+ * ```
* Launch an app
* Navigate home to show launcher
* Swipe right from the bottom of the screen to quick switch back to the app
- *
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@@ -66,25 +67,25 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
testApp.launchViaIntent(wmHelper)
tapl.goHome()
- wmHelper.StateSyncBuilder()
+ wmHelper
+ .StateSyncBuilder()
.withHomeActivityVisible()
.withWindowSurfaceDisappeared(testApp)
.waitForAndVerify()
- startDisplayBounds = wmHelper.currentState.layerState
- .physicalDisplayBounds ?: error("Display not found")
+ startDisplayBounds =
+ wmHelper.currentState.layerState.physicalDisplayBounds ?: error("Display not found")
}
transitions {
tapl.workspace.quickSwitchToPreviousApp()
- wmHelper.StateSyncBuilder()
+ wmHelper
+ .StateSyncBuilder()
.withFullScreenApp(testApp)
.withNavOrTaskBarVisible()
.withStatusBarVisible()
.waitForAndVerify()
}
- teardown {
- testApp.exit(wmHelper)
- }
+ teardown { testApp.exit(wmHelper) }
}
/**
@@ -94,9 +95,7 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Presubmit
@Test
fun endsWithAppWindowsCoveringFullScreen() {
- testSpec.assertWmEnd {
- this.visibleRegion(testApp).coversExactly(startDisplayBounds)
- }
+ testSpec.assertWmEnd { this.visibleRegion(testApp).coversExactly(startDisplayBounds) }
}
/**
@@ -106,9 +105,7 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Presubmit
@Test
fun endsWithAppLayersCoveringFullScreen() {
- testSpec.assertLayersEnd {
- this.visibleRegion(testApp).coversExactly(startDisplayBounds)
- }
+ testSpec.assertLayersEnd { this.visibleRegion(testApp).coversExactly(startDisplayBounds) }
}
/**
@@ -118,20 +115,14 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Presubmit
@Test
fun endsWithAppBeingOnTop() {
- testSpec.assertWmEnd {
- this.isAppWindowOnTop(testApp)
- }
+ testSpec.assertWmEnd { this.isAppWindowOnTop(testApp) }
}
- /**
- * Checks that the transition starts with the home activity being tagged as visible.
- */
+ /** Checks that the transition starts with the home activity being tagged as visible. */
@Presubmit
@Test
fun startsWithHomeActivityFlaggedVisible() {
- testSpec.assertWmStart {
- this.isHomeActivityVisible()
- }
+ testSpec.assertWmStart { this.isHomeActivityVisible() }
}
/**
@@ -164,9 +155,7 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Presubmit
@Test
fun startsWithLauncherBeingOnTop() {
- testSpec.assertWmStart {
- this.isAppWindowOnTop(ComponentNameMatcher.LAUNCHER)
- }
+ testSpec.assertWmStart { this.isAppWindowOnTop(ComponentNameMatcher.LAUNCHER) }
}
/**
@@ -176,9 +165,7 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Presubmit
@Test
fun endsWithHomeActivityFlaggedInvisible() {
- testSpec.assertWmEnd {
- this.isHomeActivityInvisible()
- }
+ testSpec.assertWmEnd { this.isHomeActivityInvisible() }
}
/**
@@ -188,11 +175,7 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Presubmit
@Test
fun appWindowBecomesAndStaysVisible() {
- testSpec.assertWm {
- this.isAppWindowInvisible(testApp)
- .then()
- .isAppWindowVisible(testApp)
- }
+ testSpec.assertWm { this.isAppWindowInvisible(testApp).then().isAppWindowVisible(testApp) }
}
/**
@@ -202,63 +185,59 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@Presubmit
@Test
fun appLayerBecomesAndStaysVisible() {
- testSpec.assertLayers {
- this.isInvisible(testApp)
- .then()
- .isVisible(testApp)
- }
+ testSpec.assertLayers { this.isInvisible(testApp).then().isVisible(testApp) }
}
/**
* Checks that the [ComponentMatcher.LAUNCHER] window starts off visible and becomes invisible
- * at some point before
- * the end of the transition and then stays invisible until the end of the transition.
+ * at some point before the end of the transition and then stays invisible until the end of the
+ * transition.
*/
@Presubmit
@Test
fun launcherWindowBecomesAndStaysInvisible() {
testSpec.assertWm {
this.isAppWindowOnTop(ComponentNameMatcher.LAUNCHER)
- .then()
- .isAppWindowNotOnTop(ComponentNameMatcher.LAUNCHER)
+ .then()
+ .isAppWindowNotOnTop(ComponentNameMatcher.LAUNCHER)
}
}
/**
- * Checks that the [ComponentMatcher.LAUNCHER] layer starts off visible and becomes invisible
- * at some point before
- * the end of the transition and then stays invisible until the end of the transition.
+ * Checks that the [ComponentMatcher.LAUNCHER] layer starts off visible and becomes invisible at
+ * some point before the end of the transition and then stays invisible until the end of the
+ * transition.
*/
@Presubmit
@Test
fun launcherLayerBecomesAndStaysInvisible() {
testSpec.assertLayers {
this.isVisible(ComponentNameMatcher.LAUNCHER)
- .then()
- .isInvisible(ComponentNameMatcher.LAUNCHER)
+ .then()
+ .isInvisible(ComponentNameMatcher.LAUNCHER)
}
}
/**
* Checks that the [ComponentMatcher.LAUNCHER] window is visible at least until the app window
- * is visible. Ensures
- * that at any point, either the launcher or [testApp] windows are at least partially visible.
+ * is visible. Ensures that at any point, either the launcher or [testApp] windows are at least
+ * partially visible.
*/
@Presubmit
@Test
fun appWindowIsVisibleOnceLauncherWindowIsInvisible() {
testSpec.assertWm {
this.isAppWindowOnTop(ComponentNameMatcher.LAUNCHER)
- .then()
- .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
- .then()
- .isAppWindowVisible(testApp)
+ .then()
+ .isAppWindowVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+ .then()
+ .isAppWindowVisible(testApp)
}
}
/**
- * Checks that the [ComponentMatcher.LAUNCHER] layer is visible at least until the app layer
- * is visible. Ensures that at any point, either the launcher or [testApp] layers are at least
+ * Checks that the [ComponentMatcher.LAUNCHER] layer is visible at least until the app layer is
+ * visible. Ensures that at any point, either the launcher or [testApp] layers are at least
* partially visible.
*/
@Presubmit
@@ -266,10 +245,10 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
fun appLayerIsVisibleOnceLauncherLayerIsInvisible() {
testSpec.assertLayers {
this.isVisible(ComponentNameMatcher.LAUNCHER)
- .then()
- .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
- .then()
- .isVisible(testApp)
+ .then()
+ .isVisible(ComponentNameMatcher.SNAPSHOT, isOptional = true)
+ .then()
+ .isVisible(testApp)
}
}
@@ -284,8 +263,8 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
override fun navBarWindowIsAlwaysVisible() = super.navBarWindowIsAlwaysVisible()
/**
- * Checks that [ComponentMatcher.NAV_BAR] window is visible and above the app windows at the start
- * and end of the WM trace
+ * Checks that [ComponentMatcher.NAV_BAR] window is visible and above the app windows at the
+ * start and end of the WM trace
*/
@Presubmit
@Test
@@ -316,13 +295,12 @@ class QuickSwitchFromLauncherTest(testSpec: FlickerTestParameter) : BaseTest(tes
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
return FlickerTestParameterFactory.getInstance()
- .getConfigNonRotationTests(
- supportedNavigationModes = listOf(
- WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY
- ),
- // TODO: Test with 90 rotation
- supportedRotations = listOf(Surface.ROTATION_0)
- )
+ .getConfigNonRotationTests(
+ supportedNavigationModes =
+ listOf(WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY),
+ // TODO: Test with 90 rotation
+ supportedRotations = listOf(Surface.ROTATION_0)
+ )
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
index 3ca58f2b70c0..1973ec0a98a8 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/ChangeAppRotationTest.kt
@@ -35,51 +35,54 @@ import org.junit.runners.Parameterized
* Test opening an app and cycling through app rotations
*
* Currently runs:
+ * ```
* 0 -> 90 degrees
* 90 -> 0 degrees
- *
+ * ```
* Actions:
+ * ```
* Launch an app (via intent)
* Set initial device orientation
* Start tracing
* Change device orientation
* Stop tracing
- *
+ * ```
* To run this test: `atest FlickerTests:ChangeAppRotationTest`
*
* To run only the presubmit assertions add: `--
+ * ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
- *
+ * ```
* To run only the postsubmit assertions add: `--
+ * ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
- *
+ * ```
* To run only the flaky assertions add: `--
+ * ```
* --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [RotationTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-class ChangeAppRotationTest(
- testSpec: FlickerTestParameter
-) : RotationTransition(testSpec) {
+class ChangeAppRotationTest(testSpec: FlickerTestParameter) : RotationTransition(testSpec) {
override val testApp = SimpleAppHelper(instrumentation)
override val transition: FlickerBuilder.() -> Unit
get() = {
super.transition(this)
- setup {
- testApp.launchViaIntent(wmHelper)
- }
+ setup { testApp.launchViaIntent(wmHelper) }
}
/**
@@ -89,14 +92,12 @@ class ChangeAppRotationTest(
@Presubmit
@Test
fun focusChanges() {
- testSpec.assertEventLog {
- this.focusChanges(testApp.`package`)
- }
+ testSpec.assertEventLog { this.focusChanges(testApp.`package`) }
}
/**
- * Checks that the [ComponentMatcher.ROTATION] layer appears during the transition,
- * doesn't flicker, and disappears before the transition is complete
+ * Checks that the [ComponentMatcher.ROTATION] layer appears during the transition, doesn't
+ * flicker, and disappears before the transition is complete
*/
fun rotationLayerAppearsAndVanishesAssertion() {
testSpec.assertLayers {
@@ -110,8 +111,8 @@ class ChangeAppRotationTest(
}
/**
- * Checks that the [ComponentMatcher.ROTATION] layer appears during the transition,
- * doesn't flicker, and disappears before the transition is complete
+ * Checks that the [ComponentMatcher.ROTATION] layer appears during the transition, doesn't
+ * flicker, and disappears before the transition is complete
*/
@Presubmit
@Test
@@ -122,21 +123,19 @@ class ChangeAppRotationTest(
/** {@inheritDoc} */
@FlakyTest(bugId = 206753786)
@Test
- override fun navBarLayerPositionAtStartAndEnd() =
- super.navBarLayerPositionAtStartAndEnd()
+ override fun navBarLayerPositionAtStartAndEnd() = super.navBarLayerPositionAtStartAndEnd()
companion object {
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
fun getParams(): Collection<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigRotationTests()
+ return FlickerTestParameterFactory.getInstance().getConfigRotationTests()
}
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
index afe2ea678e39..4faeb246037e 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/RotationTransition.kt
@@ -25,23 +25,15 @@ import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.traces.common.ComponentNameMatcher
import org.junit.Test
-/**
- * Base class for app rotation tests
- */
+/** Base class for app rotation tests */
abstract class RotationTransition(testSpec: FlickerTestParameter) : BaseTest(testSpec) {
protected abstract val testApp: StandardAppHelper
/** {@inheritDoc} */
override val transition: FlickerBuilder.() -> Unit = {
- setup {
- this.setRotation(testSpec.startRotation)
- }
- teardown {
- testApp.exit(wmHelper)
- }
- transitions {
- this.setRotation(testSpec.endRotation)
- }
+ setup { this.setRotation(testSpec.startRotation) }
+ teardown { testApp.exit(wmHelper) }
+ transitions { this.setRotation(testSpec.endRotation) }
}
/** {@inheritDoc} */
@@ -50,18 +42,17 @@ abstract class RotationTransition(testSpec: FlickerTestParameter) : BaseTest(tes
override fun visibleLayersShownMoreThanOneConsecutiveEntry() {
testSpec.assertLayers {
this.visibleLayersShownMoreThanOneConsecutiveEntry(
- ignoreLayers = listOf(
- ComponentNameMatcher.SPLASH_SCREEN,
- ComponentNameMatcher.SNAPSHOT,
- ComponentNameMatcher("", "SecondaryHomeHandle")
- )
+ ignoreLayers =
+ listOf(
+ ComponentNameMatcher.SPLASH_SCREEN,
+ ComponentNameMatcher.SNAPSHOT,
+ ComponentNameMatcher("", "SecondaryHomeHandle")
+ )
)
}
}
- /**
- * Checks that [testApp] layer covers the entire screen at the start of the transition
- */
+ /** Checks that [testApp] layer covers the entire screen at the start of the transition */
@Presubmit
@Test
open fun appLayerRotates_StartingPos() {
@@ -72,9 +63,7 @@ abstract class RotationTransition(testSpec: FlickerTestParameter) : BaseTest(tes
}
}
- /**
- * Checks that [testApp] layer covers the entire screen at the end of the transition
- */
+ /** Checks that [testApp] layer covers the entire screen at the end of the transition */
@Presubmit
@Test
open fun appLayerRotates_EndingPos() {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
index 11e07ebff19e..a08db29fe7a4 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/rotation/SeamlessAppRotationTest.kt
@@ -38,46 +38,51 @@ import org.junit.runners.Parameterized
* Test opening an app and cycling through app rotations using seamless rotations
*
* Currently runs:
+ * ```
* 0 -> 90 degrees
* 0 -> 90 degrees (with starved UI thread)
* 90 -> 0 degrees
* 90 -> 0 degrees (with starved UI thread)
- *
+ * ```
* Actions:
+ * ```
* Launch an app in fullscreen and supporting seamless rotation (via intent)
* Set initial device orientation
* Start tracing
* Change device orientation
* Stop tracing
- *
+ * ```
* To run this test: `atest FlickerTests:SeamlessAppRotationTest`
*
* To run only the presubmit assertions add: `--
+ * ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Presubmit`
- *
+ * ```
* To run only the postsubmit assertions add: `--
+ * ```
* --module-arg FlickerTests:exclude-annotation:androidx.test.filters.FlakyTest
* --module-arg FlickerTests:include-annotation:android.platform.test.annotations.Postsubmit`
- *
+ * ```
* To run only the flaky assertions add: `--
+ * ```
* --module-arg FlickerTests:include-annotation:androidx.test.filters.FlakyTest`
- *
+ * ```
* Notes:
+ * ```
* 1. Some default assertions (e.g., nav bar, status bar and screen covered)
* are inherited [RotationTransition]
* 2. Part of the test setup occurs automatically via
* [com.android.server.wm.flicker.TransitionRunnerWithRules],
* including configuring navigation mode, initial orientation and ensuring no
* apps are running before setup
+ * ```
*/
@RequiresDevice
@RunWith(Parameterized::class)
@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-open class SeamlessAppRotationTest(
- testSpec: FlickerTestParameter
-) : RotationTransition(testSpec) {
+open class SeamlessAppRotationTest(testSpec: FlickerTestParameter) : RotationTransition(testSpec) {
override val testApp = SeamlessRotationAppHelper(instrumentation)
/** {@inheritDoc} */
@@ -87,17 +92,16 @@ open class SeamlessAppRotationTest(
setup {
testApp.launchViaIntent(
wmHelper,
- stringExtras = mapOf(
- ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD
- to testSpec.starveUiThread.toString()
- )
+ stringExtras =
+ mapOf(
+ ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD to
+ testSpec.starveUiThread.toString()
+ )
)
}
}
- /**
- * Checks that [testApp] window is always in full screen
- */
+ /** Checks that [testApp] window is always in full screen */
@Presubmit
@Test
fun appWindowFullScreen() {
@@ -105,16 +109,15 @@ open class SeamlessAppRotationTest(
this.invoke("isFullScreen") {
val appWindow = it.windowState(testApp.`package`)
val flags = appWindow.windowState?.attributes?.flags ?: 0
- appWindow.verify("isFullScreen")
+ appWindow
+ .verify("isFullScreen")
.that(flags.and(WindowManager.LayoutParams.FLAG_FULLSCREEN))
.isGreaterThan(0)
}
}
}
- /**
- * Checks that [testApp] window is always with seamless rotation
- */
+ /** Checks that [testApp] window is always with seamless rotation */
@Presubmit
@Test
fun appWindowSeamlessRotation() {
@@ -122,38 +125,33 @@ open class SeamlessAppRotationTest(
this.invoke("isRotationSeamless") {
val appWindow = it.windowState(testApp.`package`)
val rotationAnimation = appWindow.windowState?.attributes?.rotationAnimation ?: 0
- appWindow.verify("isRotationSeamless")
+ appWindow
+ .verify("isRotationSeamless")
.that(
- rotationAnimation
- .and(WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS)
+ rotationAnimation.and(
+ WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS
+ )
)
.isGreaterThan(0)
}
}
}
- /**
- * Checks that [testApp] window is always visible
- */
+ /** Checks that [testApp] window is always visible */
@Presubmit
@Test
fun appLayerAlwaysVisible() {
- testSpec.assertLayers {
- isVisible(testApp)
- }
+ testSpec.assertLayers { isVisible(testApp) }
}
- /**
- * Checks that [testApp] layer covers the entire screen during the whole transition
- */
+ /** Checks that [testApp] layer covers the entire screen during the whole transition */
@Presubmit
@Test
fun appLayerRotates() {
testSpec.assertLayers {
this.invoke("entireScreenCovered") { entry ->
entry.entry.displays.map { display ->
- entry.visibleRegion(testApp)
- .coversExactly(display.layerStackSpace)
+ entry.visibleRegion(testApp).coversExactly(display.layerStackSpace)
}
}
}
@@ -162,20 +160,17 @@ open class SeamlessAppRotationTest(
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. App is full screen")
- override fun statusBarLayerPositionAtStartAndEnd() {
- }
+ override fun statusBarLayerPositionAtStartAndEnd() {}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. App is full screen")
- override fun statusBarLayerIsVisibleAtStartAndEnd() {
- }
+ override fun statusBarLayerIsVisibleAtStartAndEnd() {}
/** {@inheritDoc} */
@Test
@Ignore("Not applicable to this CUJ. App is full screen")
- override fun statusBarWindowIsAlwaysVisible() {
- }
+ override fun statusBarWindowIsAlwaysVisible() {}
/**
* Checks that the [ComponentNameMatcher.STATUS_BAR] window is invisible during the whole
@@ -184,9 +179,7 @@ open class SeamlessAppRotationTest(
@Presubmit
@Test
fun statusBarWindowIsAlwaysInvisible() {
- testSpec.assertWm {
- this.isAboveAppWindowInvisible(ComponentNameMatcher.STATUS_BAR)
- }
+ testSpec.assertWm { this.isAboveAppWindowInvisible(ComponentNameMatcher.STATUS_BAR) }
}
/**
@@ -196,20 +189,14 @@ open class SeamlessAppRotationTest(
@Presubmit
@Test
fun statusBarLayerIsAlwaysInvisible() {
- testSpec.assertLayers {
- this.isInvisible(ComponentNameMatcher.STATUS_BAR)
- }
+ testSpec.assertLayers { this.isInvisible(ComponentNameMatcher.STATUS_BAR) }
}
- /**
- * Checks that the focus doesn't change during animation
- */
+ /** Checks that the focus doesn't change during animation */
@Presubmit
@Test
fun focusDoesNotChange() {
- testSpec.assertEventLog {
- this.focusDoesNotChange()
- }
+ testSpec.assertEventLog { this.focusDoesNotChange() }
}
/** {@inheritDoc} */
@@ -219,15 +206,16 @@ open class SeamlessAppRotationTest(
companion object {
private val FlickerTestParameter.starveUiThread
- get() = config.getOrDefault(
- ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD, false) as Boolean
+ get() =
+ config.getOrDefault(ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD, false)
+ as Boolean
private fun createConfig(
sourceConfig: FlickerTestParameter,
starveUiThread: Boolean
): FlickerTestParameter {
- val newConfig = sourceConfig.config.toMutableMap()
- .also {
+ val newConfig =
+ sourceConfig.config.toMutableMap().also {
it[ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD] = starveUiThread
}
val nameExt = if (starveUiThread) "_BUSY_UI_THREAD" else ""
@@ -235,27 +223,26 @@ open class SeamlessAppRotationTest(
}
/**
- * Creates the test configurations for seamless rotation based on the default rotation
- * tests from [FlickerTestParameterFactory.getConfigRotationTests], but adding an
- * additional flag ([ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD]) to indicate
- * if the app should starve the UI thread of not
+ * Creates the test configurations for seamless rotation based on the default rotation tests
+ * from [FlickerTestParameterFactory.getConfigRotationTests], but adding an additional flag
+ * ([ActivityOptions.SeamlessRotation.EXTRA_STARVE_UI_THREAD]) to indicate if the app should
+ * starve the UI thread of not
*/
@JvmStatic
private fun getConfigurations(): List<FlickerTestParameter> {
- return FlickerTestParameterFactory.getInstance()
- .getConfigRotationTests()
- .flatMap { sourceConfig ->
- val defaultRun = createConfig(sourceConfig, starveUiThread = false)
- val busyUiRun = createConfig(sourceConfig, starveUiThread = true)
- listOf(defaultRun, busyUiRun)
- }
+ return FlickerTestParameterFactory.getInstance().getConfigRotationTests().flatMap {
+ sourceConfig ->
+ val defaultRun = createConfig(sourceConfig, starveUiThread = false)
+ val busyUiRun = createConfig(sourceConfig, starveUiThread = true)
+ listOf(defaultRun, busyUiRun)
+ }
}
/**
* Creates the test configurations.
*
- * See [FlickerTestParameterFactory.getConfigRotationTests] for configuring
- * repetitions, screen orientation and navigation modes.
+ * See [FlickerTestParameterFactory.getConfigRotationTests] for configuring repetitions,
+ * screen orientation and navigation modes.
*/
@Parameterized.Parameters(name = "{0}")
@JvmStatic
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt b/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
index 8aa3e2583071..4d69d26e46db 100644
--- a/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
+++ b/tools/lint/checks/src/main/java/com/google/android/lint/AndroidFrameworkIssueRegistry.kt
@@ -42,6 +42,8 @@ class AndroidFrameworkIssueRegistry : IssueRegistry() {
SaferParcelChecker.ISSUE_UNSAFE_API_USAGE,
PackageVisibilityDetector.ISSUE_PACKAGE_NAME_NO_PACKAGE_VISIBILITY_FILTERS,
RegisterReceiverFlagDetector.ISSUE_RECEIVER_EXPORTED_FLAG,
+ PermissionMethodDetector.ISSUE_PERMISSION_METHOD_USAGE,
+ PermissionMethodDetector.ISSUE_CAN_BE_PERMISSION_METHOD,
)
override val api: Int
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/Constants.kt b/tools/lint/checks/src/main/java/com/google/android/lint/Constants.kt
index 82eb8ed8f621..3d5d01c9b7a0 100644
--- a/tools/lint/checks/src/main/java/com/google/android/lint/Constants.kt
+++ b/tools/lint/checks/src/main/java/com/google/android/lint/Constants.kt
@@ -34,3 +34,7 @@ val ENFORCE_PERMISSION_METHODS = listOf(
Method(CLASS_ACTIVITY_MANAGER_SERVICE, "checkPermission"),
Method(CLASS_ACTIVITY_MANAGER_INTERNAL, "enforceCallingPermission")
)
+
+const val ANNOTATION_PERMISSION_METHOD = "android.content.pm.PermissionMethod"
+const val ANNOTATION_PERMISSION_NAME = "android.content.pm.PermissionName"
+const val ANNOTATION_PERMISSION_RESULT = "android.content.pm.PackageManager.PermissionResult"
diff --git a/tools/lint/checks/src/main/java/com/google/android/lint/PermissionMethodDetector.kt b/tools/lint/checks/src/main/java/com/google/android/lint/PermissionMethodDetector.kt
new file mode 100644
index 000000000000..68a450d956a8
--- /dev/null
+++ b/tools/lint/checks/src/main/java/com/google/android/lint/PermissionMethodDetector.kt
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.lint
+
+import com.android.tools.lint.client.api.UElementHandler
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.JavaContext
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+import com.android.tools.lint.detector.api.SourceCodeScanner
+import com.android.tools.lint.detector.api.getUMethod
+import com.intellij.psi.PsiType
+import org.jetbrains.uast.UAnnotation
+import org.jetbrains.uast.UBlockExpression
+import org.jetbrains.uast.UCallExpression
+import org.jetbrains.uast.UElement
+import org.jetbrains.uast.UExpression
+import org.jetbrains.uast.UIfExpression
+import org.jetbrains.uast.UMethod
+import org.jetbrains.uast.UQualifiedReferenceExpression
+import org.jetbrains.uast.UReturnExpression
+import org.jetbrains.uast.getContainingUMethod
+
+/**
+ * Stops incorrect usage of {@link PermissionMethod}
+ * TODO: add tests once re-enabled (b/240445172, b/247542171)
+ */
+class PermissionMethodDetector : Detector(), SourceCodeScanner {
+
+ override fun getApplicableUastTypes(): List<Class<out UElement>> =
+ listOf(UAnnotation::class.java, UMethod::class.java)
+
+ override fun createUastHandler(context: JavaContext): UElementHandler =
+ PermissionMethodHandler(context)
+
+ private inner class PermissionMethodHandler(val context: JavaContext) : UElementHandler() {
+ override fun visitMethod(node: UMethod) {
+ if (hasPermissionMethodAnnotation(node)) return
+ if (onlyCallsPermissionMethod(node)) {
+ val location = context.getLocation(node.javaPsi.modifierList)
+ val fix = fix()
+ .annotate(ANNOTATION_PERMISSION_METHOD)
+ .range(location)
+ .autoFix()
+ .build()
+
+ context.report(
+ ISSUE_CAN_BE_PERMISSION_METHOD,
+ location,
+ "Annotate method with @PermissionMethod",
+ fix
+ )
+ }
+ }
+
+ override fun visitAnnotation(node: UAnnotation) {
+ if (node.qualifiedName != ANNOTATION_PERMISSION_METHOD) return
+ val method = node.getContainingUMethod() ?: return
+
+ if (!isPermissionMethodReturnType(method)) {
+ context.report(
+ ISSUE_PERMISSION_METHOD_USAGE,
+ context.getLocation(node),
+ """
+ Methods annotated with `@PermissionMethod` should return `void`, \
+ `boolean`, or `@PackageManager.PermissionResult int`."
+ """.trimIndent()
+ )
+ }
+
+ if (method.returnType == PsiType.INT &&
+ method.annotations.none { it.hasQualifiedName(ANNOTATION_PERMISSION_RESULT) }
+ ) {
+ context.report(
+ ISSUE_PERMISSION_METHOD_USAGE,
+ context.getLocation(node),
+ """
+ Methods annotated with `@PermissionMethod` that return `int` should \
+ also be annotated with `@PackageManager.PermissionResult.`"
+ """.trimIndent()
+ )
+ }
+ }
+ }
+
+ companion object {
+
+ private val EXPLANATION_PERMISSION_METHOD_USAGE = """
+ `@PermissionMethod` should annotate methods that ONLY perform permission lookups. \
+ Said methods should return `boolean`, `@PackageManager.PermissionResult int`, or return \
+ `void` and potentially throw `SecurityException`.
+ """.trimIndent()
+
+ @JvmField
+ val ISSUE_PERMISSION_METHOD_USAGE = Issue.create(
+ id = "PermissionMethodUsage",
+ briefDescription = "@PermissionMethod used incorrectly",
+ explanation = EXPLANATION_PERMISSION_METHOD_USAGE,
+ category = Category.CORRECTNESS,
+ priority = 5,
+ severity = Severity.ERROR,
+ implementation = Implementation(
+ PermissionMethodDetector::class.java,
+ Scope.JAVA_FILE_SCOPE
+ ),
+ enabledByDefault = true
+ )
+
+ private val EXPLANATION_CAN_BE_PERMISSION_METHOD = """
+ Methods that only call other methods annotated with @PermissionMethod (and do NOTHING else) can themselves \
+ be annotated with @PermissionMethod. For example:
+ ```
+ void wrapperHelper() {
+ // Context.enforceCallingPermission is annotated with @PermissionMethod
+ context.enforceCallingPermission(SOME_PERMISSION)
+ }
+ ```
+ """.trimIndent()
+
+ @JvmField
+ val ISSUE_CAN_BE_PERMISSION_METHOD = Issue.create(
+ id = "CanBePermissionMethod",
+ briefDescription = "Method can be annotated with @PermissionMethod",
+ explanation = EXPLANATION_CAN_BE_PERMISSION_METHOD,
+ category = Category.SECURITY,
+ priority = 5,
+ severity = Severity.WARNING,
+ implementation = Implementation(
+ PermissionMethodDetector::class.java,
+ Scope.JAVA_FILE_SCOPE
+ ),
+ enabledByDefault = false
+ )
+
+ private fun hasPermissionMethodAnnotation(method: UMethod): Boolean = method.annotations
+ .any {
+ it.hasQualifiedName(ANNOTATION_PERMISSION_METHOD)
+ }
+
+ private fun isPermissionMethodReturnType(method: UMethod): Boolean =
+ listOf(PsiType.VOID, PsiType.INT, PsiType.BOOLEAN).contains(method.returnType)
+
+ /**
+ * Identifies methods that...
+ * DO call other methods annotated with @PermissionMethod
+ * DO NOT do anything else
+ */
+ private fun onlyCallsPermissionMethod(method: UMethod): Boolean {
+ val body = method.uastBody as? UBlockExpression ?: return false
+ if (body.expressions.isEmpty()) return false
+ for (expression in body.expressions) {
+ when (expression) {
+ is UQualifiedReferenceExpression -> {
+ if (!isPermissionMethodCall(expression.selector)) return false
+ }
+ is UReturnExpression -> {
+ if (!isPermissionMethodCall(expression.returnExpression)) return false
+ }
+ is UCallExpression -> {
+ if (!isPermissionMethodCall(expression)) return false
+ }
+ is UIfExpression -> {
+ if (expression.thenExpression !is UReturnExpression) return false
+ if (!isPermissionMethodCall(expression.condition)) return false
+ }
+ else -> return false
+ }
+ }
+ return true
+ }
+
+ private fun isPermissionMethodCall(expression: UExpression?): Boolean {
+ return when (expression) {
+ is UQualifiedReferenceExpression ->
+ return isPermissionMethodCall(expression.selector)
+ is UCallExpression -> {
+ val calledMethod = expression.resolve()?.getUMethod() ?: return false
+ return hasPermissionMethodAnnotation(calledMethod)
+ }
+ else -> false
+ }
+ }
+ }
+}