summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AconfigFlags.bp27
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java3
-rw-r--r--core/api/current.txt6
-rw-r--r--core/java/android/app/ActivityManager.java45
-rw-r--r--core/java/android/app/NotificationChannel.java59
-rw-r--r--core/java/android/app/activity_manager.aconfig10
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java25
-rw-r--r--core/java/android/app/admin/flags/flags.aconfig76
-rw-r--r--core/java/android/app/notification.aconfig10
-rw-r--r--core/java/android/appwidget/flags.aconfig7
-rw-r--r--core/java/android/companion/virtual/flags/flags.aconfig7
-rw-r--r--core/java/android/content/pm/multiuser.aconfig10
-rw-r--r--core/java/android/hardware/biometrics/BiometricFingerprintConstants.java1
-rw-r--r--core/java/android/hardware/location/ContextHubManager.java68
-rw-r--r--core/java/android/os/ArtModuleServiceManager.java32
-rw-r--r--core/java/android/os/BinderProxy.java42
-rw-r--r--core/java/android/os/IBinder.java49
-rw-r--r--core/java/android/os/VibrationEffect.java42
-rw-r--r--core/java/android/util/LocalLog.java5
-rw-r--r--core/java/android/view/SurfaceControl.java8
-rw-r--r--core/java/android/window/BackAnimationAdapter.java32
-rw-r--r--core/java/android/window/flags/lse_desktop_experience.aconfig7
-rw-r--r--core/java/com/android/internal/jank/FrameTracker.java61
-rw-r--r--core/java/com/android/internal/jank/flags.aconfig10
-rw-r--r--core/java/com/android/internal/policy/DecorView.java13
-rw-r--r--core/jni/android_media_AudioSystem.cpp41
-rw-r--r--core/jni/android_util_Binder.cpp446
-rw-r--r--core/jni/android_view_SurfaceControl.cpp10
-rw-r--r--core/res/res/values-fa/strings.xml2
-rw-r--r--core/res/res/values-gu/strings.xml4
-rw-r--r--core/res/res/values-nl/strings.xml2
-rw-r--r--core/res/res/values-tl/strings.xml2
-rw-r--r--core/res/res/values/strings.xml4
-rw-r--r--core/res/res/values/themes_device_defaults.xml86
-rw-r--r--core/tests/GameManagerTests/Android.bp7
-rw-r--r--core/tests/coretests/Android.bp2
-rw-r--r--core/tests/coretests/AndroidTest.xml1
-rw-r--r--core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/Android.bp34
-rw-r--r--core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/AndroidManifest.xml23
-rw-r--r--core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java71
-rw-r--r--core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java2
-rw-r--r--core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBfsccTestAppCmdService.aidl22
-rw-r--r--core/tests/coretests/src/android/app/NotificationChannelTest.java27
-rw-r--r--core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java267
-rw-r--r--core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java10
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java10
-rw-r--r--core/tests/hdmitests/Android.bp7
-rw-r--r--core/tests/mockingcoretests/Android.bp10
-rw-r--r--core/tests/timetests/Android.bp14
-rw-r--r--core/tests/vibrator/src/android/os/VibrationEffectTest.java80
-rw-r--r--libs/WindowManager/Shell/AndroidManifest.xml1
-rw-r--r--libs/WindowManager/Shell/aconfig/multitasking.aconfig5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java45
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java89
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java1
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java73
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java39
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java94
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java24
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java15
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowManagerWrapper.kt41
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt45
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt16
-rw-r--r--libs/WindowManager/Shell/tests/unittest/Android.bp7
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java3
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java93
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java4
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java22
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java8
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java19
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt8
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainerTest.kt2
-rw-r--r--media/java/android/media/MediaRouter2.java3
-rw-r--r--media/tests/AudioPolicyTest/Android.bp8
-rw-r--r--packages/SettingsLib/aconfig/settingslib.aconfig10
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values/config.xml10
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java8
-rw-r--r--packages/SettingsLib/tests/integ/Android.bp7
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java26
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/Android.bp1
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml3
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml34
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java16
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java11
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java27
-rw-r--r--packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java9
-rw-r--r--packages/SystemUI/aconfig/systemui.aconfig12
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt24
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt9
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt46
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinInputDisplay.kt15
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt6
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt9
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt5
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt9
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt9
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt5
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt9
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ActionableContent.kt46
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt9
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt15
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt27
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt2
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt9
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt65
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt102
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt6
-rw-r--r--packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt16
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt166
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt6
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt112
-rw-r--r--packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt (renamed from packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt)12
-rw-r--r--packages/SystemUI/docs/scene.md6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt3
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModelTest.kt (renamed from packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt)6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt13
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt45
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt (renamed from packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModelTest.kt)30
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt2
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModelTest.kt (renamed from packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModelTest.kt)6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelTest.kt (renamed from packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelTest.kt)4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt (renamed from packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt)6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt34
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt (renamed from packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModelTest.kt)14
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModelTest.kt (renamed from packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModelTest.kt)6
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt (renamed from packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelTest.kt)4
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java27
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt8
-rw-r--r--packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt2
-rw-r--r--packages/SystemUI/res/color/brightness_slider_track.xml19
-rw-r--r--packages/SystemUI/res/drawable/arrow_pointing_down.xml2
-rw-r--r--packages/SystemUI/res/drawable/brightness_bar.xml2
-rw-r--r--packages/SystemUI/res/drawable/brightness_progress_drawable.xml3
-rw-r--r--packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml2
-rw-r--r--packages/SystemUI/res/layout/ongoing_activity_chip.xml1
-rw-r--r--packages/SystemUI/res/layout/screen_share_dialog.xml13
-rw-r--r--packages/SystemUI/res/layout/status_bar.xml5
-rw-r--r--packages/SystemUI/res/values-af/strings.xml5
-rw-r--r--packages/SystemUI/res/values-am/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml5
-rw-r--r--packages/SystemUI/res/values-as/strings.xml5
-rw-r--r--packages/SystemUI/res/values-az/strings.xml5
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml5
-rw-r--r--packages/SystemUI/res/values-be/strings.xml5
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml7
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml5
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml7
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml5
-rw-r--r--packages/SystemUI/res/values-da/strings.xml5
-rw-r--r--packages/SystemUI/res/values-de/strings.xml7
-rw-r--r--packages/SystemUI/res/values-el/strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml5
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml2
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml7
-rw-r--r--packages/SystemUI/res/values-es/strings.xml7
-rw-r--r--packages/SystemUI/res/values-et/strings.xml5
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml5
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml5
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml5
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml5
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml5
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml5
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml11
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml9
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml5
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml5
-rw-r--r--packages/SystemUI/res/values-in/strings.xml5
-rw-r--r--packages/SystemUI/res/values-is/strings.xml5
-rw-r--r--packages/SystemUI/res/values-it/strings.xml9
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml5
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml5
-rw-r--r--packages/SystemUI/res/values-km/strings.xml5
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml7
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml5
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml5
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml5
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml5
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml5
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml5
-rw-r--r--packages/SystemUI/res/values-my/strings.xml5
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml5
-rw-r--r--packages/SystemUI/res/values-night/colors.xml6
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml7
-rw-r--r--packages/SystemUI/res/values-or/strings.xml5
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml5
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml5
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml5
-rw-r--r--packages/SystemUI/res/values-si/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml5
-rw-r--r--packages/SystemUI/res/values-te/strings.xml5
-rw-r--r--packages/SystemUI/res/values-th/strings.xml5
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml7
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml5
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml5
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml5
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml5
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml5
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml7
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml5
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml5
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml5
-rw-r--r--packages/SystemUI/res/values/colors.xml2
-rw-r--r--packages/SystemUI/res/values/dimens.xml1
-rw-r--r--packages/SystemUI/res/values/strings.xml16
-rw-r--r--packages/SystemUI/res/values/styles.xml16
-rw-r--r--packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java19
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt98
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt84
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModel.kt (renamed from packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt)8
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt43
-rw-r--r--packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt146
-rw-r--r--packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt22
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt (renamed from packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModel.kt)8
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt (renamed from packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModel.kt)8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt (renamed from packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModel.kt)8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModel.kt (renamed from packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt)8
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModel.kt (renamed from packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModel.kt)6
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModel.kt (renamed from packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt)6
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt (renamed from packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModel.kt)8
-rw-r--r--packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt314
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt304
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java25
-rw-r--r--packages/SystemUI/tests/Android.bp11
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt158
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt70
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt17
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt19
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingStateTest.kt109
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java27
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt46
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java64
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java55
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt55
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt12
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelKosmos.kt (renamed from packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt)4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeUserActionsViewModelKosmos.kt (renamed from packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneActionsViewModelKosmos.kt)6
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelKosmos.kt (renamed from packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt)4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt8
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java3
-rw-r--r--services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java195
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java12
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java13
-rw-r--r--services/core/java/com/android/server/am/UserController.java9
-rw-r--r--services/core/java/com/android/server/biometrics/PreAuthInfo.java4
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java133
-rw-r--r--services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java4
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java51
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerControllerInterface.java267
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java10
-rw-r--r--services/core/java/com/android/server/input/InputSettingsObserver.java2
-rw-r--r--services/core/java/com/android/server/input/debug/TouchpadDebugView.java139
-rw-r--r--services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java109
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java14
-rw-r--r--services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java10
-rw-r--r--services/core/java/com/android/server/notification/ManagedServices.java28
-rw-r--r--services/core/java/com/android/server/notification/ZenLog.java29
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java46
-rw-r--r--services/core/java/com/android/server/pm/RemovePackageHelper.java54
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java2
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java33
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java9
-rw-r--r--services/core/java/com/android/server/power/ThermalManagerService.java2
-rw-r--r--services/core/java/com/android/server/tv/TvInputManagerService.java19
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java15
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java17
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java22
-rw-r--r--services/core/java/com/android/server/wm/BackNavigationController.java3
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java12
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java33
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowSettings.java1
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java21
-rw-r--r--services/core/java/com/android/server/wm/WindowProcessController.java8
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java38
-rw-r--r--services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt13
-rw-r--r--services/tests/InputMethodSystemServerTests/Android.bp14
-rw-r--r--services/tests/PackageManagerServiceTests/host/Android.bp7
-rw-r--r--services/tests/PackageManagerServiceTests/server/Android.bp22
-rw-r--r--services/tests/PackageManagerServiceTests/unit/Android.bp7
-rw-r--r--services/tests/displayservicetests/Android.bp10
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java4
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java2
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java2
-rw-r--r--services/tests/dreamservicetests/Android.bp10
-rw-r--r--services/tests/mockingservicestests/Android.bp70
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java97
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp10
-rw-r--r--services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java8
-rw-r--r--services/tests/powerservicetests/Android.bp10
-rw-r--r--services/tests/powerstatstests/Android.bp20
-rw-r--r--services/tests/powerstatstests/TEST_MAPPING3
-rw-r--r--services/tests/servicestests/Android.bp173
-rw-r--r--services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt21
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UserControllerTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java4
-rw-r--r--services/tests/timetests/Android.bp24
-rw-r--r--services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java4
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java41
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java31
-rw-r--r--services/tests/wmtests/Android.bp32
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java2
-rw-r--r--telephony/common/android/telephony/LocationAccessPolicy.java17
-rw-r--r--telephony/common/com/android/internal/telephony/TelephonyPermissions.java17
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java18
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java36
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteManager.java11
-rw-r--r--telephony/java/android/telephony/satellite/stub/ISatellite.aidl9
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyProperties.java4
-rw-r--r--tests/Input/src/com/android/server/input/debug/TouchpadDebugViewControllerTests.java215
-rw-r--r--tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java292
-rw-r--r--tests/TrustTests/Android.bp7
389 files changed, 6339 insertions, 2756 deletions
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index c76812111cec..df4a3e5c3b35 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -100,6 +100,7 @@ aconfig_declarations_group {
"framework-jobscheduler-job.flags-aconfig-java",
"framework_graphics_flags_java_lib",
"hwui_flags_java_lib",
+ "interaction_jank_monitor_flags_lib",
"libcore_exported_aconfig_flags_lib",
"libgui_flags_java_lib",
"power_flags_lib",
@@ -1428,6 +1429,18 @@ java_aconfig_library {
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+java_aconfig_library {
+ name: "android.app.appfunctions.exported-flags-aconfig-java",
+ aconfig_declarations: "android.app.appfunctions.flags-aconfig",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+ mode: "exported",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.permission",
+ ],
+ min_sdk_version: "30",
+}
+
// Adaptive Auth
aconfig_declarations {
name: "android.adaptiveauth.flags-aconfig",
@@ -1578,3 +1591,17 @@ java_aconfig_library {
aconfig_declarations: "dropbox_flags",
defaults: ["framework-minus-apex-aconfig-java-defaults"],
}
+
+// Zero Jank
+aconfig_declarations {
+ name: "interaction_jank_monitor_flags",
+ package: "com.android.internal.jank",
+ container: "system",
+ srcs: ["core/java/com/android/internal/jank/flags.aconfig"],
+}
+
+java_aconfig_library {
+ name: "interaction_jank_monitor_flags_lib",
+ aconfig_declarations: "interaction_jank_monitor_flags",
+ defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
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 3d25ed5aa2b7..97c6e25eeb75 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -5808,9 +5808,10 @@ public class JobSchedulerService extends com.android.server.SystemService
static void dumpHelp(PrintWriter pw) {
pw.println("Job Scheduler (jobscheduler) dump options:");
- pw.println(" [-h] [package] ...");
+ pw.println(" [-h] [package] [--proto] ...");
pw.println(" -h: print this help");
pw.println(" [package] is an optional package name to limit the output to.");
+ pw.println(" --proto: output dump in protocol buffer format.");
}
/** Sort jobs by caller UID, then by Job ID. */
diff --git a/core/api/current.txt b/core/api/current.txt
index ddfd364cc55d..56852212ab1e 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -43963,11 +43963,11 @@ package android.telephony {
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_CONNECTION_HYSTERESIS_SEC_INT = "satellite_connection_hysteresis_sec_int";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_STATUS_REFRESH_DAYS_INT = "satellite_entitlement_status_refresh_days_int";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_enabled_satellite_flag") public static final String KEY_SATELLITE_ENTITLEMENT_SUPPORTED_BOOL = "satellite_entitlement_supported_bool";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_esos_inactivity_timeout_sec_int";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ESOS_SUPPORTED_BOOL = "satellite_esos_supported_bool";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_p2p_sms_inactivity_timeout_sec_int";
+ field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_esos_inactivity_timeout_sec_int";
+ field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_p2p_sms_inactivity_timeout_sec_int";
field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_P2P_SMS_SUPPORTED_BOOL = "satellite_roaming_p2p_sms_supported_bool";
- field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT = "satellite_screen_off_inactivity_timeout_sec_int";
+ field @FlaggedApi("com.android.internal.telephony.flags.carrier_roaming_nb_iot_ntn") public static final String KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT = "satellite_roaming_screen_off_inactivity_timeout_sec_int";
field public static final String KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL = "show_4g_for_3g_data_icon_bool";
field public static final String KEY_SHOW_4G_FOR_LTE_DATA_ICON_BOOL = "show_4g_for_lte_data_icon_bool";
field public static final String KEY_SHOW_APN_SETTING_CDMA_BOOL = "show_apn_setting_cdma_bool";
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 68063c4a1a50..b83be6b86d04 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -66,6 +66,7 @@ import android.os.Bundle;
import android.os.Debug;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IpcDataCache;
import android.os.LocaleList;
import android.os.Parcel;
import android.os.Parcelable;
@@ -238,6 +239,44 @@ public class ActivityManager {
new RateLimitingCache<>(10, 2);
/**
+ * Query handler for mGetCurrentUserIdCache - returns a cached value of the current foreground
+ * user id if the backstage_power/android.app.cache_get_current_user_id flag is enabled.
+ */
+ private static final IpcDataCache.QueryHandler<Void, Integer> mGetCurrentUserIdQuery =
+ new IpcDataCache.QueryHandler<>() {
+ @Override
+ public Integer apply(Void query) {
+ try {
+ return getService().getCurrentUserId();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ public boolean shouldBypassCache(Void query) {
+ // If the flag to enable the new caching behavior is off, bypass the cache.
+ return !Flags.cacheGetCurrentUserId();
+ }
+ };
+
+ /** A cache which maintains the current foreground user id. */
+ private static final IpcDataCache<Void, Integer> mGetCurrentUserIdCache =
+ new IpcDataCache<>(1, IpcDataCache.MODULE_SYSTEM,
+ /* api= */ "getCurrentUserId", /* cacheName= */ "CurrentUserIdCache",
+ mGetCurrentUserIdQuery);
+
+ /**
+ * The current foreground user has changed - invalidate the cache. Currently only called from
+ * UserController when a user switch occurs.
+ * @hide
+ */
+ public static void invalidateGetCurrentUserIdCache() {
+ IpcDataCache.invalidateCache(
+ IpcDataCache.MODULE_SYSTEM, /* api= */ "getCurrentUserId");
+ }
+
+ /**
* Map of callbacks that have registered for {@link UidFrozenStateChanged} events.
* Will be called when a Uid has become frozen or unfrozen.
*/
@@ -5244,11 +5283,7 @@ public class ActivityManager {
})
@android.ravenwood.annotation.RavenwoodReplace
public static int getCurrentUser() {
- try {
- return getService().getCurrentUserId();
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ return mGetCurrentUserIdCache.query(null);
}
/** @hide */
diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java
index 789c99d8e017..1b29b7a294df 100644
--- a/core/java/android/app/NotificationChannel.java
+++ b/core/java/android/app/NotificationChannel.java
@@ -168,7 +168,11 @@ public final class NotificationChannel implements Parcelable {
/**
* @hide
*/
- public static final int MAX_VIBRATION_LENGTH = 1000;
+ public static final int MAX_VIBRATION_LENGTH = 500;
+ /**
+ * @hide
+ */
+ public static final int MAX_SERIALIZED_VIBRATION_LENGTH = 32_768;
private static final String TAG_CHANNEL = "channel";
private static final String ATT_NAME = "name";
@@ -368,6 +372,9 @@ public final class NotificationChannel implements Parcelable {
if (Flags.notificationChannelVibrationEffectApi()) {
mVibrationEffect =
in.readInt() != 0 ? VibrationEffect.CREATOR.createFromParcel(in) : null;
+ if (Flags.notifChannelCropVibrationEffects() && mVibrationEffect != null) {
+ mVibrationEffect = getTrimmedVibrationEffect(mVibrationEffect);
+ }
}
mUserLockedFields = in.readInt();
mUserVisibleTaskShown = in.readByte() != 0;
@@ -582,6 +589,23 @@ public final class NotificationChannel implements Parcelable {
return input;
}
+ // Returns trimmed vibration effect or null if not trimmable.
+ private VibrationEffect getTrimmedVibrationEffect(VibrationEffect effect) {
+ if (effect == null) {
+ return null;
+ }
+ // trim if possible; check serialized length; reject if it is still too long
+ VibrationEffect result = effect;
+ VibrationEffect trimmed = effect.cropToLengthOrNull(MAX_VIBRATION_LENGTH);
+ if (trimmed != null) {
+ result = trimmed;
+ }
+ if (vibrationToString(result).length() > MAX_SERIALIZED_VIBRATION_LENGTH) {
+ return null;
+ }
+ return result;
+ }
+
/**
* @hide
*/
@@ -685,6 +709,11 @@ public final class NotificationChannel implements Parcelable {
public void setVibrationPattern(long[] vibrationPattern) {
this.mVibrationEnabled = vibrationPattern != null && vibrationPattern.length > 0;
this.mVibrationPattern = vibrationPattern;
+ if (Flags.notifChannelCropVibrationEffects()) {
+ if (vibrationPattern != null && vibrationPattern.length > MAX_VIBRATION_LENGTH) {
+ this.mVibrationPattern = Arrays.copyOf(vibrationPattern, MAX_VIBRATION_LENGTH);
+ }
+ }
if (Flags.notificationChannelVibrationEffectApi()) {
try {
this.mVibrationEffect =
@@ -731,9 +760,21 @@ public final class NotificationChannel implements Parcelable {
public void setVibrationEffect(@Nullable VibrationEffect effect) {
this.mVibrationEnabled = effect != null;
this.mVibrationEffect = effect;
- this.mVibrationPattern =
- effect == null
- ? null : effect.computeCreateWaveformOffOnTimingsOrNull();
+ if (Flags.notifChannelCropVibrationEffects() && effect != null) {
+ // Try converting to a vibration pattern and trimming that array. If not convertible
+ // to a pattern directly, try trimming the vibration effect if possible and storing
+ // that version instead.
+ long[] pattern = effect.computeCreateWaveformOffOnTimingsOrNull();
+ if (pattern != null) {
+ setVibrationPattern(pattern);
+ } else {
+ this.mVibrationEffect = getTrimmedVibrationEffect(mVibrationEffect);
+ }
+ } else {
+ this.mVibrationPattern =
+ mVibrationEffect == null
+ ? null : mVibrationEffect.computeCreateWaveformOffOnTimingsOrNull();
+ }
}
/**
@@ -1172,7 +1213,9 @@ public final class NotificationChannel implements Parcelable {
if (vibrationEffect != null) {
// Restore the effect only if it is not null. This allows to avoid undoing a
// `setVibrationPattern` call above, if that was done with a non-null pattern
- // (e.g. back up from a version that did not support `setVibrationEffect`).
+ // (e.g. back up from a version that did not support `setVibrationEffect`), or
+ // when notif_channel_crop_vibration_effects is true, if there is an equivalent
+ // vibration pattern available.
setVibrationEffect(vibrationEffect);
}
}
@@ -1365,7 +1408,11 @@ public final class NotificationChannel implements Parcelable {
out.attribute(null, ATT_VIBRATION, longArrayToString(getVibrationPattern()));
}
if (getVibrationEffect() != null) {
- out.attribute(null, ATT_VIBRATION_EFFECT, vibrationToString(getVibrationEffect()));
+ if (!Flags.notifChannelCropVibrationEffects() || getVibrationPattern() == null) {
+ // When notif_channel_crop_vibration_effects is on, only serialize the vibration
+ // effect if we do not already have an equivalent vibration pattern.
+ out.attribute(null, ATT_VIBRATION_EFFECT, vibrationToString(getVibrationEffect()));
+ }
}
if (getUserLockedFields() != 0) {
out.attributeInt(null, ATT_USER_LOCKED, getUserLockedFields());
diff --git a/core/java/android/app/activity_manager.aconfig b/core/java/android/app/activity_manager.aconfig
index 32e6e80cc3e9..4c97dbbb4d01 100644
--- a/core/java/android/app/activity_manager.aconfig
+++ b/core/java/android/app/activity_manager.aconfig
@@ -104,3 +104,13 @@ flag {
}
}
+flag {
+ namespace: "backstage_power"
+ name: "cache_get_current_user_id"
+ description: "Add caching for getCurrentUserId"
+ is_fixed_read_only: true
+ bug: "361853873"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 1ddec17e49bb..0f54cb7bc35e 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -10476,10 +10476,6 @@ public class DevicePolicyManager {
@WorkerThread
public void setApplicationRestrictions(@Nullable ComponentName admin, String packageName,
Bundle settings) {
- if (!Flags.dmrhSetAppRestrictions()) {
- throwIfParentInstance("setApplicationRestrictions");
- }
-
if (mService != null) {
try {
mService.setApplicationRestrictions(admin, mContext.getPackageName(), packageName,
@@ -11884,9 +11880,6 @@ public class DevicePolicyManager {
@WorkerThread
public @NonNull Bundle getApplicationRestrictions(
@Nullable ComponentName admin, String packageName) {
- if (!Flags.dmrhSetAppRestrictions()) {
- throwIfParentInstance("getApplicationRestrictions");
- }
if (mService != null) {
try {
@@ -14231,21 +14224,11 @@ public class DevicePolicyManager {
*/
public @NonNull DevicePolicyManager getParentProfileInstance(@NonNull ComponentName admin) {
throwIfParentInstance("getParentProfileInstance");
- try {
- if (Flags.dmrhSetAppRestrictions()) {
- UserManager um = mContext.getSystemService(UserManager.class);
- if (!um.isManagedProfile()) {
- throw new SecurityException("The current user does not have a parent profile.");
- }
- } else {
- if (!mService.isManagedProfile(admin)) {
- throw new SecurityException("The current user does not have a parent profile.");
- }
- }
- return new DevicePolicyManager(mContext, mService, true);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
+ UserManager um = mContext.getSystemService(UserManager.class);
+ if (!um.isManagedProfile()) {
+ throw new SecurityException("The current user does not have a parent profile.");
}
+ return new DevicePolicyManager(mContext, mService, true);
}
/**
diff --git a/core/java/android/app/admin/flags/flags.aconfig b/core/java/android/app/admin/flags/flags.aconfig
index d9bd77fb3d54..faa5a910b28a 100644
--- a/core/java/android/app/admin/flags/flags.aconfig
+++ b/core/java/android/app/admin/flags/flags.aconfig
@@ -97,6 +97,62 @@ flag {
bug: "356894721"
}
+flag {
+ name: "reset_password_with_token_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for resetPasswordWithToken and setResetPasswordToken."
+ bug: "359187209"
+}
+
+flag {
+ name: "set_keyguard_disabled_features_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setKeyguardDisabledFeatures."
+ bug: "359186276"
+}
+
+flag {
+ name: "set_application_restrictions_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setApplicationRestrictions."
+ bug: "359188153"
+}
+
+flag {
+ name: "set_auto_time_enabled_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setAutoTimeEnabled."
+ bug: "359188869"
+}
+
+flag {
+ name: "set_backup_service_enabled_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setBackupServiceEnabled."
+ bug: "359188483"
+}
+
+flag {
+ name: "set_auto_time_zone_enabled_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setAutoTimeZoneEnabled."
+ bug: "364338300"
+}
+
+flag {
+ name: "set_permission_grant_state_coexistence"
+ is_exported: true
+ namespace: "enterprise"
+ description: "Enables coexistence support for setPermissionGrantState."
+ bug: "364338410"
+}
+
# Fully rolled out and must not be used.
flag {
name: "security_log_v2_enabled"
@@ -210,16 +266,6 @@ flag {
}
flag {
- name: "dmrh_set_app_restrictions"
- namespace: "enterprise"
- description: "Allow DMRH to set application restrictions (both on the profile and the parent)"
- bug: "328758346"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "always_persist_do"
namespace: "enterprise"
description: "Always write device_owners2.xml so that migration flags aren't lost"
@@ -267,16 +313,6 @@ flag {
}
flag {
- name: "headless_single_user_fixes"
- namespace: "enterprise"
- description: "Various fixes for headless single user mode"
- bug: "289515470"
- metadata {
- purpose: PURPOSE_BUGFIX
- }
-}
-
-flag {
name: "backup_connected_apps_settings"
namespace: "enterprise"
description: "backup and restore connected work and personal apps user settings across devices"
diff --git a/core/java/android/app/notification.aconfig b/core/java/android/app/notification.aconfig
index 606ca3393de0..9891e8930936 100644
--- a/core/java/android/app/notification.aconfig
+++ b/core/java/android/app/notification.aconfig
@@ -128,6 +128,16 @@ flag {
}
flag {
+ name: "notif_channel_crop_vibration_effects"
+ namespace: "systemui"
+ description: "Limits the size of vibration effects that can be stored in a NotificationChannel"
+ bug: "345881518"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "evenly_divided_call_style_action_layout"
namespace: "systemui"
description: "Evenly divides horizontal space for action buttons in CallStyle notifications."
diff --git a/core/java/android/appwidget/flags.aconfig b/core/java/android/appwidget/flags.aconfig
index 4e0379e3dc3a..7117f250d1d5 100644
--- a/core/java/android/appwidget/flags.aconfig
+++ b/core/java/android/appwidget/flags.aconfig
@@ -57,3 +57,10 @@ flag {
description: "Enable support for persisting RemoteViews previews to Protobuf"
bug: "306546610"
}
+
+flag {
+ name: "remote_document_support"
+ namespace: "app_widgets"
+ description: "Remote document support features in Q2 2025 release"
+ bug: "339721781"
+} \ No newline at end of file
diff --git a/core/java/android/companion/virtual/flags/flags.aconfig b/core/java/android/companion/virtual/flags/flags.aconfig
index 22a9ccf425c2..297fe8a9e691 100644
--- a/core/java/android/companion/virtual/flags/flags.aconfig
+++ b/core/java/android/companion/virtual/flags/flags.aconfig
@@ -111,3 +111,10 @@ flag {
description: "Device awareness in power and display APIs"
bug: "285020111"
}
+
+flag {
+ name: "status_bar_and_insets"
+ namespace: "virtual_devices"
+ description: "Allow for status bar and insets on virtual devices"
+ bug: "350007866"
+}
diff --git a/core/java/android/content/pm/multiuser.aconfig b/core/java/android/content/pm/multiuser.aconfig
index 3a33ef9002cc..28534ad4516e 100644
--- a/core/java/android/content/pm/multiuser.aconfig
+++ b/core/java/android/content/pm/multiuser.aconfig
@@ -161,6 +161,16 @@ flag {
}
flag {
+ name: "fix_avatar_content_provider_null_authority"
+ namespace: "multiuser"
+ description: "Fix crash when content provider authority is null."
+ bug: "362880068"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
+
+flag {
name: "fix_avatar_picker_not_responding_for_new_user"
namespace: "multiuser"
description: "Avatar picker is not responding after selecting photo for new user."
diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
index fc72db3c5791..6682b367e977 100644
--- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
+++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java
@@ -61,7 +61,6 @@ public interface BiometricFingerprintConstants {
BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL,
BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
BIOMETRIC_ERROR_RE_ENROLL,
- BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
FINGERPRINT_ERROR_UNKNOWN,
FINGERPRINT_ERROR_BAD_CALIBRATION,
BIOMETRIC_ERROR_POWER_PRESSED})
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index 3a589930feb4..218b02315fc8 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -256,6 +256,10 @@ public final class ContextHubManager {
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public int[] getContextHubHandles() {
+ if (Flags.removeOldContextHubApis()) {
+ return null;
+ }
+
try {
return mService.getContextHubHandles();
} catch (RemoteException e) {
@@ -277,6 +281,10 @@ public final class ContextHubManager {
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public ContextHubInfo getContextHubInfo(int hubHandle) {
+ if (Flags.removeOldContextHubApis()) {
+ return null;
+ }
+
try {
return mService.getContextHubInfo(hubHandle);
} catch (RemoteException e) {
@@ -308,6 +316,10 @@ public final class ContextHubManager {
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public int loadNanoApp(int hubHandle, @NonNull NanoApp app) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
try {
return mService.loadNanoApp(hubHandle, app);
} catch (RemoteException e) {
@@ -335,6 +347,10 @@ public final class ContextHubManager {
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public int unloadNanoApp(int nanoAppHandle) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
try {
return mService.unloadNanoApp(nanoAppHandle);
} catch (RemoteException e) {
@@ -375,6 +391,10 @@ public final class ContextHubManager {
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
@Nullable public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
+ if (Flags.removeOldContextHubApis()) {
+ return null;
+ }
+
try {
return mService.getNanoAppInstanceInfo(nanoAppHandle);
} catch (RemoteException e) {
@@ -398,6 +418,10 @@ public final class ContextHubManager {
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
@NonNull public int[] findNanoAppOnHub(int hubHandle, @NonNull NanoAppFilter filter) {
+ if (Flags.removeOldContextHubApis()) {
+ return null;
+ }
+
try {
return mService.findNanoAppOnHub(hubHandle, filter);
} catch (RemoteException e) {
@@ -433,6 +457,10 @@ public final class ContextHubManager {
@Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_CONTEXT_HUB)
public int sendMessage(int hubHandle, int nanoAppHandle, @NonNull ContextHubMessage message) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
try {
return mService.sendMessage(hubHandle, nanoAppHandle, message);
} catch (RemoteException e) {
@@ -648,6 +676,10 @@ public final class ContextHubManager {
@Deprecated
@SuppressLint("RequiresPermission")
public int registerCallback(@NonNull Callback callback) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
return registerCallback(callback, null);
}
@@ -657,6 +689,10 @@ public final class ContextHubManager {
*/
@Deprecated
public int registerCallback(ICallback callback) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
if (mLocalCallback != null) {
Log.w(TAG, "Max number of local callbacks reached!");
return -1;
@@ -682,6 +718,10 @@ public final class ContextHubManager {
@Deprecated
@SuppressLint("RequiresPermission")
public int registerCallback(Callback callback, Handler handler) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
synchronized(this) {
if (mCallback != null) {
Log.w(TAG, "Max number of callbacks reached!");
@@ -1041,16 +1081,20 @@ public final class ContextHubManager {
@SuppressLint("RequiresPermission")
@Deprecated
public int unregisterCallback(@NonNull Callback callback) {
- synchronized(this) {
- if (callback != mCallback) {
- Log.w(TAG, "Cannot recognize callback!");
- return -1;
- }
-
- mCallback = null;
- mCallbackHandler = null;
- }
- return 0;
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
+ synchronized (this) {
+ if (callback != mCallback) {
+ Log.w(TAG, "Cannot recognize callback!");
+ return -1;
+ }
+
+ mCallback = null;
+ mCallbackHandler = null;
+ }
+ return 0;
}
/**
@@ -1059,6 +1103,10 @@ public final class ContextHubManager {
*/
@Deprecated
public synchronized int unregisterCallback(ICallback callback) {
+ if (Flags.removeOldContextHubApis()) {
+ return -1;
+ }
+
if (callback != mLocalCallback) {
Log.w(TAG, "Cannot recognize local callback!");
return -1;
diff --git a/core/java/android/os/ArtModuleServiceManager.java b/core/java/android/os/ArtModuleServiceManager.java
index e0b631d69ca8..995094bb1318 100644
--- a/core/java/android/os/ArtModuleServiceManager.java
+++ b/core/java/android/os/ArtModuleServiceManager.java
@@ -37,10 +37,12 @@ public class ArtModuleServiceManager {
/** A class that exposes the method to obtain each system service. */
public static final class ServiceRegisterer {
@NonNull private final String mServiceName;
+ private final boolean mRetry;
/** @hide */
- public ServiceRegisterer(@NonNull String serviceName) {
+ public ServiceRegisterer(@NonNull String serviceName, boolean retry) {
mServiceName = serviceName;
+ mRetry = retry;
}
/**
@@ -53,27 +55,47 @@ public class ArtModuleServiceManager {
*/
@Nullable
public IBinder waitForService() {
- return ServiceManager.waitForService(mServiceName);
+ if (mRetry) {
+ return ServiceManager.waitForService(mServiceName);
+ }
+ IBinder binder = ServiceManager.getService(mServiceName);
+ for (int remainingTimeMs = 5000; binder == null && remainingTimeMs > 0;
+ remainingTimeMs -= 100) {
+ // There can be a race:
+ // 1. Client A invokes "ctl.start", which starts the service.
+ // 2. Client A gets a service handle from `ServiceManager.getService`.
+ // 3. Client B invokes "ctl.start", which does nothing because the service is
+ // already running.
+ // 4. Client A drops the service handle. The service is notified that there is no
+ // more client at that point, so it shuts down itself.
+ // 5. Client B cannot get a service handle from `ServiceManager.getService` because
+ // the service is shut down.
+ // To address this problem, we invoke "ctl.start" repeatedly.
+ SystemProperties.set("ctl.start", mServiceName);
+ SystemClock.sleep(100);
+ binder = ServiceManager.getService(mServiceName);
+ }
+ return binder;
}
}
/** Returns {@link ServiceRegisterer} for the "artd" service. */
@NonNull
public ServiceRegisterer getArtdServiceRegisterer() {
- return new ServiceRegisterer("artd");
+ return new ServiceRegisterer("artd", true /* retry */);
}
/** Returns {@link ServiceRegisterer} for the "artd_pre_reboot" service. */
@NonNull
@FlaggedApi(Flags.FLAG_USE_ART_SERVICE_V2)
public ServiceRegisterer getArtdPreRebootServiceRegisterer() {
- return new ServiceRegisterer("artd_pre_reboot");
+ return new ServiceRegisterer("artd_pre_reboot", false /* retry */);
}
/** Returns {@link ServiceRegisterer} for the "dexopt_chroot_setup" service. */
@NonNull
@FlaggedApi(Flags.FLAG_USE_ART_SERVICE_V2)
public ServiceRegisterer getDexoptChrootSetupServiceRegisterer() {
- return new ServiceRegisterer("dexopt_chroot_setup");
+ return new ServiceRegisterer("dexopt_chroot_setup", true /* retry */);
}
}
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 1100731702a2..c22f46cdc2b5 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -646,6 +646,37 @@ public final class BinderProxy implements IBinder {
private native boolean unlinkToDeathNative(DeathRecipient recipient, int flags);
/**
+ * This list is to hold strong reference to the frozen state callbacks. The callbacks are only
+ * weakly referenced by JNI so the strong references here are needed to keep the callbacks
+ * around until the proxy is GC'ed.
+ */
+ private List<IFrozenStateChangeCallback> mFrozenStateChangeCallbacks =
+ Collections.synchronizedList(new ArrayList<>());
+
+ /**
+ * See {@link IBinder#addFrozenStateChangeCallback(IFrozenStateChangeCallback)}
+ */
+ public void addFrozenStateChangeCallback(IFrozenStateChangeCallback callback)
+ throws RemoteException {
+ addFrozenStateChangeCallbackNative(callback);
+ mFrozenStateChangeCallbacks.add(callback);
+ }
+
+ /**
+ * See {@link IBinder#removeFrozenStateChangeCallback}
+ */
+ public boolean removeFrozenStateChangeCallback(IFrozenStateChangeCallback callback) {
+ mFrozenStateChangeCallbacks.remove(callback);
+ return removeFrozenStateChangeCallbackNative(callback);
+ }
+
+ private native void addFrozenStateChangeCallbackNative(IFrozenStateChangeCallback callback)
+ throws RemoteException;
+
+ private native boolean removeFrozenStateChangeCallbackNative(
+ IFrozenStateChangeCallback callback);
+
+ /**
* Perform a dump on the remote object
*
* @param fd The raw file descriptor that the dump is being sent to.
@@ -730,6 +761,17 @@ public final class BinderProxy implements IBinder {
}
}
+ private static void invokeFrozenStateChangeCallback(
+ IFrozenStateChangeCallback callback, IBinder binderProxy, int stateIndex) {
+ try {
+ callback.onFrozenStateChanged(binderProxy,
+ IFrozenStateChangeCallback.State.values()[stateIndex]);
+ } catch (RuntimeException exc) {
+ Log.w("BinderNative", "Uncaught exception from frozen state change callback",
+ exc);
+ }
+ }
+
/**
* C++ pointer to BinderProxyNativeData. That consists of strong pointers to the
* native IBinder object, and a DeathRecipientList.
diff --git a/core/java/android/os/IBinder.java b/core/java/android/os/IBinder.java
index 50242bad191b..8185e8e542e1 100644
--- a/core/java/android/os/IBinder.java
+++ b/core/java/android/os/IBinder.java
@@ -376,4 +376,53 @@ public interface IBinder {
* return value instead.
*/
public boolean unlinkToDeath(@NonNull DeathRecipient recipient, int flags);
+
+ /** @hide */
+ interface IFrozenStateChangeCallback {
+ enum State {FROZEN, UNFROZEN};
+
+ /**
+ * Interface for receiving a callback when the process hosting an IBinder
+ * has changed its frozen state.
+ * @param who The IBinder whose hosting process has changed state.
+ * @param state The latest state.
+ */
+ void onFrozenStateChanged(@NonNull IBinder who, State state);
+ }
+
+ /**
+ * {@link addFrozenStateChangeCallback} provides a callback mechanism to notify about process
+ * frozen/unfrozen events. Upon registration and any subsequent state changes, the callback is
+ * invoked with the latest process frozen state.
+ *
+ * <p>If the listener process (the one using this API) is itself frozen, state change events
+ * might be combined into a single one with the latest frozen state. This single event would
+ * then be delivered when the listener process becomes unfrozen. Similarly, if an event happens
+ * before the previous event is consumed, they might be combined. This means the callback might
+ * not be called for every single state change, so don't rely on this API to count how many
+ * times the state has changed.</p>
+ *
+ * <p>The callback is automatically removed when all references to the binder proxy are
+ * dropped.</p>
+ *
+ * <p>You will only receive state change notifications for remote binders, as local binders by
+ * definition can't be frozen without you being frozen too.</p>
+ *
+ * <p>@throws {@link UnsupportedOperationException} if the kernel binder driver does not support
+ * this feature.
+ * @hide
+ */
+ default void addFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback)
+ throws RemoteException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Unregister a {@link IFrozenStateChangeCallback}. The callback will no longer be invoked when
+ * the hosting process changes its frozen state.
+ * @hide
+ */
+ default boolean removeFrozenStateChangeCallback(@NonNull IFrozenStateChangeCallback callback) {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index f02d4a9ce4a7..64a2dbcb6a83 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -540,6 +540,17 @@ public abstract class VibrationEffect implements Parcelable {
/** @hide */
public abstract void validate();
+
+ /**
+ * If supported, truncate the length of this vibration effect to the provided length and return
+ * the result. Will always return null for repeating effects.
+ *
+ * @return The desired effect, or {@code null} if truncation is not applicable.
+ * @hide
+ */
+ @Nullable
+ public abstract VibrationEffect cropToLengthOrNull(int length);
+
/**
* Gets the estimated duration of the vibration in milliseconds.
*
@@ -866,6 +877,30 @@ public abstract class VibrationEffect implements Parcelable {
}
}
+ /** @hide */
+ @Override
+ @Nullable
+ public VibrationEffect cropToLengthOrNull(int length) {
+ // drop repeating effects
+ if (mRepeatIndex >= 0) {
+ return null;
+ }
+
+ int segmentCount = mSegments.size();
+ if (segmentCount <= length) {
+ return this;
+ }
+
+ ArrayList truncated = new ArrayList(mSegments.subList(0, length));
+ Composed updated = new Composed(truncated, mRepeatIndex);
+ try {
+ updated.validate();
+ } catch (IllegalArgumentException e) {
+ return null;
+ }
+ return updated;
+ }
+
@Override
public long getDuration() {
if (mRepeatIndex >= 0) {
@@ -1150,6 +1185,13 @@ public abstract class VibrationEffect implements Parcelable {
"Vendor effect bundle must be non-empty");
}
+ /** @hide */
+ @Override
+ @Nullable
+ public VibrationEffect cropToLengthOrNull(int length) {
+ return null;
+ }
+
@Override
public long getDuration() {
return -1; // UNKNOWN
diff --git a/core/java/android/util/LocalLog.java b/core/java/android/util/LocalLog.java
index feb80cc28e77..ca5798a80a10 100644
--- a/core/java/android/util/LocalLog.java
+++ b/core/java/android/util/LocalLog.java
@@ -112,6 +112,11 @@ public final class LocalLog {
}
}
+ // @VisibleForTesting(otherwise = VisibleForTesting.NONE)
+ public synchronized void clear() {
+ mLog.clear();
+ }
+
public static class ReadOnlyLocalLog {
private final LocalLog mLog;
ReadOnlyLocalLog(LocalLog log) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 9e4b27d3fa55..2dda835436bc 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -445,16 +445,20 @@ public final class SurfaceControl implements Parcelable {
// Jank due to unknown reasons.
public static final int UNKNOWN = 0x80;
- public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs) {
+ public JankData(long frameVsyncId, @JankType int jankType, long frameIntervalNs,
+ long scheduledAppFrameTimeNs, long actualAppFrameTimeNs) {
this.frameVsyncId = frameVsyncId;
this.jankType = jankType;
this.frameIntervalNs = frameIntervalNs;
-
+ this.scheduledAppFrameTimeNs = scheduledAppFrameTimeNs;
+ this.actualAppFrameTimeNs = actualAppFrameTimeNs;
}
public final long frameVsyncId;
public final @JankType int jankType;
public final long frameIntervalNs;
+ public final long scheduledAppFrameTimeNs;
+ public final long actualAppFrameTimeNs;
}
/**
diff --git a/core/java/android/window/BackAnimationAdapter.java b/core/java/android/window/BackAnimationAdapter.java
index 5eb34e694a57..153e153331e2 100644
--- a/core/java/android/window/BackAnimationAdapter.java
+++ b/core/java/android/window/BackAnimationAdapter.java
@@ -16,9 +16,12 @@
package android.window;
+import android.annotation.NonNull;
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.ArrayList;
+
/**
* Object that describes how to run a remote back animation.
*
@@ -26,6 +29,7 @@ import android.os.Parcelable;
*/
public class BackAnimationAdapter implements Parcelable {
private final IBackAnimationRunner mRunner;
+ private int[] mSupportedAnimators;
public BackAnimationAdapter(IBackAnimationRunner runner) {
mRunner = runner;
@@ -33,12 +37,23 @@ public class BackAnimationAdapter implements Parcelable {
public BackAnimationAdapter(Parcel in) {
mRunner = IBackAnimationRunner.Stub.asInterface(in.readStrongBinder());
+ mSupportedAnimators = new int[in.readInt()];
+ in.readIntArray(mSupportedAnimators);
}
public IBackAnimationRunner getRunner() {
return mRunner;
}
+ /** Update the latest animators in the system. */
+ public void updateSupportedAnimators(@NonNull ArrayList<Integer> animators) {
+ final int size = animators.size();
+ mSupportedAnimators = new int[size];
+ for (int i = size - 1; i >= 0; --i) {
+ mSupportedAnimators[i] = animators.get(i);
+ }
+ }
+
@Override
public int describeContents() {
return 0;
@@ -47,6 +62,8 @@ public class BackAnimationAdapter implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStrongInterface(mRunner);
+ dest.writeInt(mSupportedAnimators.length);
+ dest.writeIntArray(mSupportedAnimators);
}
public static final @android.annotation.NonNull Creator<BackAnimationAdapter> CREATOR =
@@ -59,4 +76,19 @@ public class BackAnimationAdapter implements Parcelable {
return new BackAnimationAdapter[size];
}
};
+
+ /**
+ * Check if the back type is animatable.
+ */
+ public boolean isAnimatable(@BackNavigationInfo.BackTargetType int backType) {
+ if (mSupportedAnimators == null) {
+ return false;
+ }
+ for (int i = mSupportedAnimators.length - 1; i >= 0; --i) {
+ if (backType == mSupportedAnimators[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/core/java/android/window/flags/lse_desktop_experience.aconfig b/core/java/android/window/flags/lse_desktop_experience.aconfig
index ebf87f1d1dba..cab6d8e9774a 100644
--- a/core/java/android/window/flags/lse_desktop_experience.aconfig
+++ b/core/java/android/window/flags/lse_desktop_experience.aconfig
@@ -245,3 +245,10 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "enable_desktop_windowing_persistence"
+ namespace: "lse_desktop_experience"
+ description: "Persists the desktop windowing session across reboots."
+ bug: "350456942"
+}
diff --git a/core/java/com/android/internal/jank/FrameTracker.java b/core/java/com/android/internal/jank/FrameTracker.java
index 53ef49bd3f65..d474c6db4f02 100644
--- a/core/java/com/android/internal/jank/FrameTracker.java
+++ b/core/java/com/android/internal/jank/FrameTracker.java
@@ -127,7 +127,7 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
private Runnable mWaitForFinishTimedOut;
private static class JankInfo {
- long frameVsyncId;
+ final long frameVsyncId;
long totalDurationNanos;
boolean isFirstFrame;
boolean hwuiCallbackFired;
@@ -135,29 +135,42 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
@JankType int jankType;
@RefreshRate int refreshRate;
- static JankInfo createFromHwuiCallback(long frameVsyncId, long totalDurationNanos,
- boolean isFirstFrame) {
- return new JankInfo(frameVsyncId, true, false, JANK_NONE, UNKNOWN_REFRESH_RATE,
- totalDurationNanos, isFirstFrame);
+ static JankInfo createFromHwuiCallback(
+ long frameVsyncId, long totalDurationNanos, boolean isFirstFrame) {
+ return new JankInfo(frameVsyncId).update(totalDurationNanos, isFirstFrame);
}
- static JankInfo createFromSurfaceControlCallback(long frameVsyncId,
- @JankType int jankType, @RefreshRate int refreshRate) {
- return new JankInfo(
- frameVsyncId, false, true, jankType, refreshRate, 0, false /* isFirstFrame */);
+ static JankInfo createFromSurfaceControlCallback(SurfaceControl.JankData jankStat) {
+ return new JankInfo(jankStat.frameVsyncId).update(jankStat);
}
- private JankInfo(long frameVsyncId, boolean hwuiCallbackFired,
- boolean surfaceControlCallbackFired, @JankType int jankType,
- @RefreshRate int refreshRate,
- long totalDurationNanos, boolean isFirstFrame) {
+ private JankInfo(long frameVsyncId) {
this.frameVsyncId = frameVsyncId;
- this.hwuiCallbackFired = hwuiCallbackFired;
- this.surfaceControlCallbackFired = surfaceControlCallbackFired;
- this.jankType = jankType;
- this.refreshRate = refreshRate;
- this.totalDurationNanos = totalDurationNanos;
+ this.hwuiCallbackFired = false;
+ this.surfaceControlCallbackFired = false;
+ this.jankType = JANK_NONE;
+ this.refreshRate = UNKNOWN_REFRESH_RATE;
+ this.totalDurationNanos = 0;
+ this.isFirstFrame = false;
+ }
+
+ private JankInfo update(SurfaceControl.JankData jankStat) {
+ this.surfaceControlCallbackFired = true;
+ this.jankType = jankStat.jankType;
+ this.refreshRate = DisplayRefreshRate.getRefreshRate(jankStat.frameIntervalNs);
+ if (Flags.useSfFrameDuration()) {
+ this.totalDurationNanos = jankStat.actualAppFrameTimeNs;
+ }
+ return this;
+ }
+
+ private JankInfo update(long totalDurationNanos, boolean isFirstFrame) {
+ this.hwuiCallbackFired = true;
+ if (!Flags.useSfFrameDuration()) {
+ this.totalDurationNanos = totalDurationNanos;
+ }
this.isFirstFrame = isFirstFrame;
+ return this;
}
@Override
@@ -457,16 +470,12 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
if (!isInRange(jankStat.frameVsyncId)) {
continue;
}
- int refreshRate = DisplayRefreshRate.getRefreshRate(jankStat.frameIntervalNs);
JankInfo info = findJankInfo(jankStat.frameVsyncId);
if (info != null) {
- info.surfaceControlCallbackFired = true;
- info.jankType = jankStat.jankType;
- info.refreshRate = refreshRate;
+ info.update(jankStat);
} else {
mJankInfos.put((int) jankStat.frameVsyncId,
- JankInfo.createFromSurfaceControlCallback(
- jankStat.frameVsyncId, jankStat.jankType, refreshRate));
+ JankInfo.createFromSurfaceControlCallback(jankStat));
}
}
processJankInfos();
@@ -513,9 +522,7 @@ public class FrameTracker implements HardwareRendererObserver.OnFrameMetricsAvai
}
JankInfo info = findJankInfo(frameVsyncId);
if (info != null) {
- info.hwuiCallbackFired = true;
- info.totalDurationNanos = totalDurationNanos;
- info.isFirstFrame = isFirstFrame;
+ info.update(totalDurationNanos, isFirstFrame);
} else {
mJankInfos.put((int) frameVsyncId, JankInfo.createFromHwuiCallback(
frameVsyncId, totalDurationNanos, isFirstFrame));
diff --git a/core/java/com/android/internal/jank/flags.aconfig b/core/java/com/android/internal/jank/flags.aconfig
new file mode 100644
index 000000000000..b6b8bc5ac44c
--- /dev/null
+++ b/core/java/com/android/internal/jank/flags.aconfig
@@ -0,0 +1,10 @@
+package: "com.android.internal.jank"
+container: "system"
+
+flag {
+ name: "use_sf_frame_duration"
+ namespace: "android_platform_window_surfaces"
+ description: "Whether to get the frame duration from SurfaceFlinger, or HWUI"
+ bug: "354763298"
+ is_fixed_read_only: true
+}
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 48283930595d..58818f35de22 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -63,6 +63,9 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.InsetDrawable;
import android.graphics.drawable.LayerDrawable;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.Pair;
@@ -114,6 +117,7 @@ import com.android.internal.widget.floatingtoolbar.FloatingToolbar;
import com.android.window.flags.Flags;
import java.util.List;
+import java.util.concurrent.Executor;
import java.util.function.Consumer;
/** @hide */
@@ -1348,8 +1352,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
mCrossWindowBlurEnabled = enabled;
updateBackgroundBlurRadius();
};
+ // The executor to receive callback {@link mCrossWindowBlurEnabledListener}. It
+ // should be the executor for this {@link DecorView}'s ui thread (not necessarily
+ // the main thread).
+ final Executor executor = Looper.myLooper() == Looper.getMainLooper()
+ ? getContext().getMainExecutor()
+ : new HandlerExecutor(new Handler(Looper.myLooper()));
getContext().getSystemService(WindowManager.class)
- .addCrossWindowBlurEnabledListener(mCrossWindowBlurEnabledListener);
+ .addCrossWindowBlurEnabledListener(
+ executor, mCrossWindowBlurEnabledListener);
getViewTreeObserver().addOnPreDrawListener(mBackgroundBlurOnPreDrawListener);
} else {
updateBackgroundBlurRadius();
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 46710b5d3edc..9bccf5af7096 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -3379,44 +3379,39 @@ class JavaSystemPropertyListener {
public:
JavaSystemPropertyListener(JNIEnv* env, jobject javaCallback, std::string sysPropName) :
mCallback {javaCallback, env},
- mPi {__system_property_find(sysPropName.c_str())},
+ mSysPropName(sysPropName),
+ mCachedProperty(android::base::CachedProperty{std::move(sysPropName)}),
mListenerThread([this](mediautils::stop_token stok) mutable {
- static const struct timespec close_delay = { .tv_sec = 1 };
while (!stok.stop_requested()) {
- uint32_t old_serial = mSerial.load();
- uint32_t new_serial;
- if (__system_property_wait(mPi, old_serial, &new_serial, &close_delay)) {
- while (new_serial > old_serial) {
- if (mSerial.compare_exchange_weak(old_serial, new_serial)) {
- fireUpdate();
- break;
- }
- }
- }
+ using namespace std::chrono_literals;
+ // 1s timeout so this thread can eventually respond to the stop token
+ std::string newVal = mCachedProperty.WaitForChange(1000ms) ?: "";
+ updateValue(newVal);
}
}) {}
void triggerUpdateIfChanged() {
- uint32_t old_serial = mSerial.load();
- uint32_t new_serial = __system_property_serial(mPi);
- while (new_serial > old_serial) {
- if (mSerial.compare_exchange_weak(old_serial, new_serial)) {
- fireUpdate();
- break;
- }
- }
+ // We must check the property without using the cached property due to thread safety issues
+ std::string newVal = base::GetProperty(mSysPropName, "");
+ updateValue(newVal);
}
private:
- void fireUpdate() {
+ void updateValue(std::string newVal) {
+ if (newVal == "") return;
+ std::lock_guard l{mLock};
+ if (mLastVal == newVal) return;
const auto threadEnv = GetOrAttachJNIEnvironment(gVm);
threadEnv->CallVoidMethod(mCallback.get(), gRunnableClassInfo.run);
+ mLastVal = std::move(newVal);
}
// Should outlive thread object
const GlobalRef mCallback;
- const prop_info * const mPi;
- std::atomic<uint32_t> mSerial = 0;
+ const std::string mSysPropName;
+ android::base::CachedProperty mCachedProperty;
+ std::string mLastVal = "";
+ std::mutex mLock;
const mediautils::jthread mListenerThread;
};
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 46b4695a9cec..921b77d61f4d 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -56,11 +56,11 @@
//#undef ALOGV
//#define ALOGV(...) fprintf(stderr, __VA_ARGS__)
-#define DEBUG_DEATH 0
-#if DEBUG_DEATH
-#define LOGDEATH ALOGD
+#define DEBUG_DEATH_FREEZE 0
+#if DEBUG_DEATH_FREEZE
+#define LOG_DEATH_FREEZE ALOGD
#else
-#define LOGDEATH ALOGV
+#define LOG_DEATH_FREEZE ALOGV
#endif
using namespace android;
@@ -116,6 +116,7 @@ static struct binderproxy_offsets_t
jclass mClass;
jmethodID mGetInstance;
jmethodID mSendDeathNotice;
+ jmethodID mInvokeFrozenStateChangeCallback;
// Object state.
jfieldID mNativeData; // Field holds native pointer to BinderProxyNativeData.
@@ -547,23 +548,59 @@ private:
// ----------------------------------------------------------------------------
-// Per-IBinder death recipient bookkeeping. This is how we reconcile local jobject
-// death recipient references passed in through JNI with the permanent corresponding
-// JavaDeathRecipient objects.
-
-class JavaDeathRecipient;
-
-class DeathRecipientList : public RefBase {
- List< sp<JavaDeathRecipient> > mList;
+// A JavaRecipient receives either death notifications or frozen state change
+// callbacks from natve code (IBinder) and dispatch the notifications to its
+// corresponding Java listener object.
+//
+// A RecipientList keeps tracks of all JavaRecipients for an IBinder. This way
+// we can find a JavaRecipient given a Java listener object.
+//
+// The implementation is shared between death recipients and frozen state change
+// callbacks via template. For death recipients the template is instantiated as
+// follows:
+//
+// IBinder::DeathRecipient
+// ^
+// |
+// (inherits)
+// |
+// JavaRecipient<IBinder::DeathRecipient> <----> RecipientList<IBinder::DeathRecipient>
+// ^
+// |
+// (inherits)
+// |
+// JavaDeathRecipient
+//
+//
+// The instantiation for frozen state change callbacks are:
+//
+// IBinder::FrozenStateChangeCallback
+// ^
+// |
+// (inherits)
+// |
+// JavaRecipient<IBinder::FrozenStateChangeCallback>
+// ^ ^
+// | |
+// (inherits) +--> RecipientList<IBinder::FrozenStateChangeCallback>
+// |
+// JavaFrozenStateChangeCallback
+
+template <typename T>
+class JavaRecipient;
+
+template <typename T>
+class RecipientList : public RefBase {
+ List<sp<JavaRecipient<T> > > mList;
Mutex mLock;
public:
- DeathRecipientList();
- ~DeathRecipientList();
+ RecipientList();
+ ~RecipientList();
- void add(const sp<JavaDeathRecipient>& recipient);
- void remove(const sp<JavaDeathRecipient>& recipient);
- sp<JavaDeathRecipient> find(jobject recipient);
+ void add(const sp<JavaRecipient<T> >& recipient);
+ void remove(const sp<JavaRecipient<T> >& recipient);
+ sp<JavaRecipient<T> > find(jobject recipient);
Mutex& lock(); // Use with care; specifically for mutual exclusion during binder death
};
@@ -584,11 +621,113 @@ static constexpr bool target_sdk_is_at_least_vic() {
#endif // __BIONIC__
#endif // BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI
-class JavaDeathRecipient : public IBinder::DeathRecipient
-{
+template <typename T>
+constexpr const char* logPrefix();
+
+template <>
+constexpr const char* logPrefix<IBinder::DeathRecipient>() {
+ return "[DEATH]";
+}
+
+template <>
+constexpr const char* logPrefix<IBinder::FrozenStateChangeCallback>() {
+ return "[FREEZE]";
+}
+
+template <typename T>
+class JavaRecipient : public T {
public:
- JavaDeathRecipient(JNIEnv* env, jobject object, const sp<DeathRecipientList>& list)
+ JavaRecipient(JNIEnv* env, jobject object, const sp<RecipientList<T> >& list,
+ bool useWeakReference)
: mVM(jnienv_to_javavm(env)), mObject(NULL), mObjectWeak(NULL), mList(list) {
+ if (useWeakReference) {
+ mObjectWeak = env->NewWeakGlobalRef(object);
+ } else {
+ mObject = env->NewGlobalRef(object);
+ }
+ // These objects manage their own lifetimes so are responsible for final bookkeeping.
+ // The list holds a strong reference to this object.
+ LOG_DEATH_FREEZE("%s Adding JavaRecipient %p to RecipientList %p", logPrefix<T>(), this,
+ list.get());
+ list->add(this);
+ }
+
+ void clearReference() {
+ sp<RecipientList<T> > list = mList.promote();
+ if (list != NULL) {
+ LOG_DEATH_FREEZE("%s Removing JavaRecipient %p from RecipientList %p", logPrefix<T>(),
+ this, list.get());
+ list->remove(this);
+ } else {
+ LOG_DEATH_FREEZE("%s clearReference() on JavaRecipient %p but RecipientList wp purged",
+ logPrefix<T>(), this);
+ }
+ }
+
+ bool matches(jobject obj) {
+ bool result;
+ JNIEnv* env = javavm_to_jnienv(mVM);
+
+ if (mObject != NULL) {
+ result = env->IsSameObject(obj, mObject);
+ } else {
+ ScopedLocalRef<jobject> me(env, env->NewLocalRef(mObjectWeak));
+ result = env->IsSameObject(obj, me.get());
+ }
+ return result;
+ }
+
+ void warnIfStillLive() {
+ if (mObject != NULL) {
+ // Okay, something is wrong -- we have a hard reference to a live death
+ // recipient on the VM side, but the list is being torn down.
+ JNIEnv* env = javavm_to_jnienv(mVM);
+ ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject));
+ ScopedLocalRef<jstring> nameRef(env,
+ (jstring)env->CallObjectMethod(objClassRef.get(),
+ gClassOffsets.mGetName));
+ ScopedUtfChars nameUtf(env, nameRef.get());
+ if (nameUtf.c_str() != NULL) {
+ ALOGW("BinderProxy is being destroyed but the application did not call "
+ "unlinkToDeath to unlink all of its death recipients beforehand. "
+ "Releasing leaked death recipient: %s",
+ nameUtf.c_str());
+ } else {
+ ALOGW("BinderProxy being destroyed; unable to get DR object name");
+ env->ExceptionClear();
+ }
+ }
+ }
+
+protected:
+ virtual ~JavaRecipient() {
+ // ALOGI("Removing death ref: recipient=%p\n", mObject);
+ JNIEnv* env = javavm_to_jnienv(mVM);
+ if (mObject != NULL) {
+ env->DeleteGlobalRef(mObject);
+ } else {
+ env->DeleteWeakGlobalRef(mObjectWeak);
+ }
+ }
+
+ JavaVM* const mVM;
+
+ // If useWeakReference is false (e.g. JavaDeathRecipient when target sdk version < 35), the
+ // Java-side Recipient is strongly referenced from mObject initially, and may later be demoted
+ // to a weak reference (mObjectWeak), e.g. upon linkToDeath() and then after binderDied() is
+ // called.
+ // If useWeakReference is true, the strong reference is never made here (i.e. mObject == NULL
+ // always). Instead, the strong reference to the Java-side Recipient is made in
+ // BinderProxy.{mDeathRecipients,mFrozenStateChangeCallbacks}. In the native world, only the
+ // weak reference is kept.
+ jobject mObject;
+ jweak mObjectWeak;
+ wp<RecipientList<T> > mList;
+};
+
+class JavaDeathRecipient : public JavaRecipient<IBinder::DeathRecipient> {
+public:
+ static bool useWeakReference() {
// b/298374304: For apps targeting Android V or beyond, we no longer hold the global JNI ref
// to the death recipient objects. This is to prevent the memory leak which can happen when
// the death recipient object internally has a strong reference to the proxy object. Under
@@ -604,25 +743,26 @@ public:
// reference to. If however you want to get binderDied() regardless of the proxy object's
// lifecycle, keep a strong reference to the death recipient object by yourself.
#ifdef BINDER_DEATH_RECIPIENT_WEAK_FROM_JNI
- if (target_sdk_is_at_least_vic()) {
- mObjectWeak = env->NewWeakGlobalRef(object);
- } else
+ return target_sdk_is_at_least_vic();
+#else
+ return false;
#endif
- {
- mObject = env->NewGlobalRef(object);
- }
- // These objects manage their own lifetimes so are responsible for final bookkeeping.
- // The list holds a strong reference to this object.
- LOGDEATH("Adding JDR %p to DRL %p", this, list.get());
- list->add(this);
+ }
+ JavaDeathRecipient(JNIEnv* env, jobject object,
+ const sp<RecipientList<IBinder::DeathRecipient> >& list)
+ : JavaRecipient(env, object, list, useWeakReference()) {
gNumDeathRefsCreated.fetch_add(1, std::memory_order_relaxed);
gcIfManyNewRefs(env);
}
+ ~JavaDeathRecipient() {
+ gNumDeathRefsDeleted.fetch_add(1, std::memory_order_relaxed);
+ }
+
void binderDied(const wp<IBinder>& who)
{
- LOGDEATH("Receiving binderDied() on JavaDeathRecipient %p\n", this);
+ LOG_DEATH_FREEZE("Receiving binderDied() on JavaDeathRecipient %p\n", this);
if (mObject == NULL && mObjectWeak == NULL) {
return;
}
@@ -662,7 +802,7 @@ public:
// with our containing DeathRecipientList so that we can't delete the global ref on mObject
// while the list is being iterated.
if (mObject != NULL) {
- sp<DeathRecipientList> list = mList.promote();
+ auto list = mList.promote();
if (list != NULL) {
AutoMutex _l(list->lock());
@@ -673,126 +813,96 @@ public:
}
}
- void clearReference()
- {
- sp<DeathRecipientList> list = mList.promote();
- if (list != NULL) {
- LOGDEATH("Removing JDR %p from DRL %p", this, list.get());
- list->remove(this);
- } else {
- LOGDEATH("clearReference() on JDR %p but DRL wp purged", this);
- }
- }
-
- bool matches(jobject obj) {
- bool result;
- JNIEnv* env = javavm_to_jnienv(mVM);
+private:
+ // Whether binderDied was called or not.
+ bool mFired = false;
+};
- if (mObject != NULL) {
- result = env->IsSameObject(obj, mObject);
- } else {
- ScopedLocalRef<jobject> me(env, env->NewLocalRef(mObjectWeak));
- result = env->IsSameObject(obj, me.get());
+class JavaFrozenStateChangeCallback : public JavaRecipient<IBinder::FrozenStateChangeCallback> {
+public:
+ JavaFrozenStateChangeCallback(
+ JNIEnv* env, jobject object,
+ const sp<RecipientList<IBinder::FrozenStateChangeCallback> >& list)
+ : JavaRecipient(env, object, list, /*useWeakReference=*/true) {}
+
+ void onStateChanged(const wp<IBinder>& who, State state) {
+ LOG_DEATH_FREEZE("Receiving onStateChanged() on JavaFrozenStateChangeCallback %p. state: "
+ "%s\n",
+ this, state == State::FROZEN ? "FROZEN" : "UNFROZEN");
+ if (mObjectWeak == NULL) {
+ return;
}
- return result;
- }
+ JNIEnv* env = javavm_to_jnienv(mVM);
+ ScopedLocalRef<jobject> jBinderProxy(env, javaObjectForIBinder(env, who.promote()));
- void warnIfStillLive() {
- if (mObject != NULL) {
- // Okay, something is wrong -- we have a hard reference to a live death
- // recipient on the VM side, but the list is being torn down.
- JNIEnv* env = javavm_to_jnienv(mVM);
- ScopedLocalRef<jclass> objClassRef(env, env->GetObjectClass(mObject));
- ScopedLocalRef<jstring> nameRef(env,
- (jstring) env->CallObjectMethod(objClassRef.get(), gClassOffsets.mGetName));
- ScopedUtfChars nameUtf(env, nameRef.get());
- if (nameUtf.c_str() != NULL) {
- ALOGW("BinderProxy is being destroyed but the application did not call "
- "unlinkToDeath to unlink all of its death recipients beforehand. "
- "Releasing leaked death recipient: %s", nameUtf.c_str());
- } else {
- ALOGW("BinderProxy being destroyed; unable to get DR object name");
- env->ExceptionClear();
- }
+ // Hold a local reference to the recipient. This may fail if the recipient is weakly
+ // referenced, in which case we can't deliver the notification.
+ ScopedLocalRef<jobject> jCallback(env, env->NewLocalRef(mObjectWeak));
+ if (jCallback.get() == NULL) {
+ return;
}
- }
-
-protected:
- virtual ~JavaDeathRecipient()
- {
- //ALOGI("Removing death ref: recipient=%p\n", mObject);
- gNumDeathRefsDeleted.fetch_add(1, std::memory_order_relaxed);
- JNIEnv* env = javavm_to_jnienv(mVM);
- if (mObject != NULL) {
- env->DeleteGlobalRef(mObject);
- } else {
- env->DeleteWeakGlobalRef(mObjectWeak);
+ env->CallStaticVoidMethod(gBinderProxyOffsets.mClass,
+ gBinderProxyOffsets.mInvokeFrozenStateChangeCallback,
+ jCallback.get(), jBinderProxy.get(), state);
+ if (env->ExceptionCheck()) {
+ jthrowable excep = env->ExceptionOccurred();
+ binder_report_exception(env, excep,
+ "*** Uncaught exception returned from frozen state change "
+ "notification!");
}
}
-
-private:
- JavaVM* const mVM;
-
- // If target sdk version < 35, the Java-side DeathRecipient is strongly referenced from mObject
- // upon linkToDeath() and then after binderDied() is called, the strong reference is demoted to
- // a weak reference (mObjectWeak).
- // If target sdk version >= 35, the strong reference is never made here (i.e. mObject == NULL
- // always). Instead, the strong reference to the Java-side DeathRecipient is made in
- // BinderProxy.mDeathRecipients. In the native world, only the weak reference is kept.
- jobject mObject;
- jweak mObjectWeak;
- wp<DeathRecipientList> mList;
-
- // Whether binderDied was called or not.
- bool mFired = false;
};
// ----------------------------------------------------------------------------
-DeathRecipientList::DeathRecipientList() {
- LOGDEATH("New DRL @ %p", this);
+template <typename T>
+RecipientList<T>::RecipientList() {
+ LOG_DEATH_FREEZE("%s New RecipientList @ %p", logPrefix<T>(), this);
}
-DeathRecipientList::~DeathRecipientList() {
- LOGDEATH("Destroy DRL @ %p", this);
+template <typename T>
+RecipientList<T>::~RecipientList() {
+ LOG_DEATH_FREEZE("%s Destroy RecipientList @ %p", logPrefix<T>(), this);
AutoMutex _l(mLock);
- // Should never happen -- the JavaDeathRecipient objects that have added themselves
+ // Should never happen -- the JavaRecipientList objects that have added themselves
// to the list are holding references on the list object. Only when they are torn
// down can the list header be destroyed.
if (mList.size() > 0) {
- List< sp<JavaDeathRecipient> >::iterator iter;
- for (iter = mList.begin(); iter != mList.end(); iter++) {
+ for (auto iter = mList.begin(); iter != mList.end(); iter++) {
(*iter)->warnIfStillLive();
}
}
}
-void DeathRecipientList::add(const sp<JavaDeathRecipient>& recipient) {
+template <typename T>
+void RecipientList<T>::add(const sp<JavaRecipient<T> >& recipient) {
AutoMutex _l(mLock);
- LOGDEATH("DRL @ %p : add JDR %p", this, recipient.get());
+ LOG_DEATH_FREEZE("%s RecipientList @ %p : add JavaRecipient %p", logPrefix<T>(), this,
+ recipient.get());
mList.push_back(recipient);
}
-void DeathRecipientList::remove(const sp<JavaDeathRecipient>& recipient) {
+template <typename T>
+void RecipientList<T>::remove(const sp<JavaRecipient<T> >& recipient) {
AutoMutex _l(mLock);
- List< sp<JavaDeathRecipient> >::iterator iter;
- for (iter = mList.begin(); iter != mList.end(); iter++) {
+ for (auto iter = mList.begin(); iter != mList.end(); iter++) {
if (*iter == recipient) {
- LOGDEATH("DRL @ %p : remove JDR %p", this, recipient.get());
+ LOG_DEATH_FREEZE("%s RecipientList @ %p : remove JavaRecipient %p", logPrefix<T>(),
+ this, recipient.get());
mList.erase(iter);
return;
}
}
}
-sp<JavaDeathRecipient> DeathRecipientList::find(jobject recipient) {
+template <typename T>
+sp<JavaRecipient<T> > RecipientList<T>::find(jobject recipient) {
AutoMutex _l(mLock);
- List< sp<JavaDeathRecipient> >::iterator iter;
- for (iter = mList.begin(); iter != mList.end(); iter++) {
+ for (auto iter = mList.begin(); iter != mList.end(); iter++) {
if ((*iter)->matches(recipient)) {
return *iter;
}
@@ -800,10 +910,14 @@ sp<JavaDeathRecipient> DeathRecipientList::find(jobject recipient) {
return NULL;
}
-Mutex& DeathRecipientList::lock() {
+template <typename T>
+Mutex& RecipientList<T>::lock() {
return mLock;
}
+using DeathRecipientList = RecipientList<IBinder::DeathRecipient>;
+using FrozenStateChangeCallbackList = RecipientList<IBinder::FrozenStateChangeCallback>;
+
// ----------------------------------------------------------------------------
namespace android {
@@ -821,6 +935,11 @@ struct BinderProxyNativeData {
// Death recipients for mObject. Reference counted only because DeathRecipients
// hold a weak reference that can be temporarily promoted.
sp<DeathRecipientList> mOrgue; // Death recipients for mObject.
+
+ // Frozen state change callbacks for mObject. Reference counted only because
+ // JavaFrozenStateChangeCallback hold a weak reference that can be
+ // temporarily promoted.
+ sp<FrozenStateChangeCallbackList> mFrozenStateChangCallbackList;
};
BinderProxyNativeData* getBPNativeData(JNIEnv* env, jobject obj) {
@@ -840,12 +959,13 @@ jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
if (val->checkSubclass(&gBinderOffsets)) {
// It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
jobject object = static_cast<JavaBBinder*>(val.get())->object();
- LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
+ LOG_DEATH_FREEZE("objectForBinder %p: it's our own %p!\n", val.get(), object);
return object;
}
BinderProxyNativeData* nativeData = new BinderProxyNativeData();
nativeData->mOrgue = new DeathRecipientList;
+ nativeData->mFrozenStateChangCallbackList = new FrozenStateChangeCallbackList;
nativeData->mObject = val;
jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
@@ -1448,7 +1568,7 @@ static void android_os_BinderProxy_linkToDeath(JNIEnv* env, jobject obj,
BinderProxyNativeData *nd = getBPNativeData(env, obj);
IBinder* target = nd->mObject.get();
- LOGDEATH("linkToDeath: binder=%p recipient=%p\n", target, recipient);
+ LOG_DEATH_FREEZE("linkToDeath: binder=%p recipient=%p\n", target, recipient);
if (!target->localBinder()) {
DeathRecipientList* list = nd->mOrgue.get();
@@ -1479,15 +1599,15 @@ static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj,
return JNI_FALSE;
}
- LOGDEATH("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
+ LOG_DEATH_FREEZE("unlinkToDeath: binder=%p recipient=%p\n", target, recipient);
if (!target->localBinder()) {
status_t err = NAME_NOT_FOUND;
// If we find the matching recipient, proceed to unlink using that
DeathRecipientList* list = nd->mOrgue.get();
- sp<JavaDeathRecipient> origJDR = list->find(recipient);
- LOGDEATH(" unlink found list %p and JDR %p", list, origJDR.get());
+ sp<JavaRecipient<IBinder::DeathRecipient> > origJDR = list->find(recipient);
+ LOG_DEATH_FREEZE(" unlink found list %p and JDR %p", list, origJDR.get());
if (origJDR != NULL) {
wp<IBinder::DeathRecipient> dr;
err = target->unlinkToDeath(origJDR, NULL, flags, &dr);
@@ -1513,11 +1633,85 @@ static jboolean android_os_BinderProxy_unlinkToDeath(JNIEnv* env, jobject obj,
return res;
}
+static void android_os_BinderProxy_addFrozenStateChangeCallback(
+ JNIEnv* env, jobject obj,
+ jobject callback) // throws RemoteException
+{
+ if (callback == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return;
+ }
+
+ BinderProxyNativeData* nd = getBPNativeData(env, obj);
+ IBinder* target = nd->mObject.get();
+
+ LOG_DEATH_FREEZE("addFrozenStateChangeCallback: binder=%p callback=%p\n", target, callback);
+
+ if (!target->localBinder()) {
+ FrozenStateChangeCallbackList* list = nd->mFrozenStateChangCallbackList.get();
+ auto jfscc = sp<JavaFrozenStateChangeCallback>::make(env, callback, list);
+ status_t err = target->addFrozenStateChangeCallback(jfscc);
+ if (err != NO_ERROR) {
+ // Failure adding the callback, so clear its reference now.
+ jfscc->clearReference();
+ signalExceptionForError(env, obj, err, true /*canThrowRemoteException*/);
+ }
+ }
+}
+
+static jboolean android_os_BinderProxy_removeFrozenStateChangeCallback(JNIEnv* env, jobject obj,
+ jobject callback) {
+ jboolean res = JNI_FALSE;
+ if (callback == NULL) {
+ jniThrowNullPointerException(env, NULL);
+ return res;
+ }
+
+ BinderProxyNativeData* nd = getBPNativeData(env, obj);
+ IBinder* target = nd->mObject.get();
+ if (target == NULL) {
+ ALOGW("Binder has been finalized when calling removeFrozenStateChangeCallback() with "
+ "callback=%p)\n",
+ callback);
+ return JNI_FALSE;
+ }
+
+ LOG_DEATH_FREEZE("removeFrozenStateChangeCallback: binder=%p callback=%p\n", target, callback);
+
+ if (!target->localBinder()) {
+ status_t err = NAME_NOT_FOUND;
+
+ // If we find the matching callback, proceed to unlink using that
+ FrozenStateChangeCallbackList* list = nd->mFrozenStateChangCallbackList.get();
+ sp<JavaRecipient<IBinder::FrozenStateChangeCallback> > origJFSCC = list->find(callback);
+ LOG_DEATH_FREEZE(" removeFrozenStateChangeCallback found list %p and JFSCC %p", list,
+ origJFSCC.get());
+ if (origJFSCC != NULL) {
+ err = target->removeFrozenStateChangeCallback(origJFSCC);
+ if (err == NO_ERROR) {
+ origJFSCC->clearReference();
+ }
+ }
+
+ if (err == NO_ERROR || err == DEAD_OBJECT) {
+ res = JNI_TRUE;
+ } else {
+ jniThrowException(env, "java/util/NoSuchElementException",
+ base::StringPrintf("Frozen state change callback does not exist (%s)",
+ statusToString(err).c_str())
+ .c_str());
+ }
+ }
+
+ return res;
+}
+
static void BinderProxy_destroy(void* rawNativeData)
{
BinderProxyNativeData * nativeData = (BinderProxyNativeData *) rawNativeData;
- LOGDEATH("Destroying BinderProxy: binder=%p drl=%p\n",
- nativeData->mObject.get(), nativeData->mOrgue.get());
+ LOG_DEATH_FREEZE("Destroying BinderProxy: binder=%p drl=%p fsccl=%p\n",
+ nativeData->mObject.get(), nativeData->mOrgue.get(),
+ nativeData->mFrozenStateChangCallbackList.get());
delete nativeData;
IPCThreadState::self()->flushCommands();
}
@@ -1552,6 +1746,10 @@ static const JNINativeMethod gBinderProxyMethods[] = {
{"transactNative", "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},
{"linkToDeathNative", "(Landroid/os/IBinder$DeathRecipient;I)V", (void*)android_os_BinderProxy_linkToDeath},
{"unlinkToDeathNative", "(Landroid/os/IBinder$DeathRecipient;I)Z", (void*)android_os_BinderProxy_unlinkToDeath},
+ {"addFrozenStateChangeCallbackNative",
+ "(Landroid/os/IBinder$IFrozenStateChangeCallback;)V", (void*)android_os_BinderProxy_addFrozenStateChangeCallback},
+ {"removeFrozenStateChangeCallbackNative",
+ "(Landroid/os/IBinder$IFrozenStateChangeCallback;)Z", (void*)android_os_BinderProxy_removeFrozenStateChangeCallback},
{"getNativeFinalizer", "()J", (void*)android_os_BinderProxy_getNativeFinalizer},
{"getExtension", "()Landroid/os/IBinder;", (void*)android_os_BinderProxy_getExtension},
};
@@ -1574,6 +1772,10 @@ static int int_register_android_os_BinderProxy(JNIEnv* env)
gBinderProxyOffsets.mSendDeathNotice =
GetStaticMethodIDOrDie(env, clazz, "sendDeathNotice",
"(Landroid/os/IBinder$DeathRecipient;Landroid/os/IBinder;)V");
+ gBinderProxyOffsets.mInvokeFrozenStateChangeCallback =
+ GetStaticMethodIDOrDie(env, clazz, "invokeFrozenStateChangeCallback",
+ "(Landroid/os/IBinder$IFrozenStateChangeCallback;Landroid/os/"
+ "IBinder;I)V");
gBinderProxyOffsets.mNativeData = GetFieldIDOrDie(env, clazz, "mNativeData", "J");
clazz = FindClassOrDie(env, "java/lang/Class");
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 0f531641903a..17c89f88b441 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -2089,9 +2089,11 @@ public:
jobjectArray jJankDataArray = env->NewObjectArray(jankData.size(),
gJankDataClassInfo.clazz, nullptr);
for (size_t i = 0; i < jankData.size(); i++) {
- jobject jJankData = env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor,
- jankData[i].frameVsyncId, jankData[i].jankType,
- jankData[i].frameIntervalNs);
+ jobject jJankData =
+ env->NewObject(gJankDataClassInfo.clazz, gJankDataClassInfo.ctor,
+ jankData[i].frameVsyncId, jankData[i].jankType,
+ jankData[i].frameIntervalNs, jankData[i].scheduledAppFrameTimeNs,
+ jankData[i].actualAppFrameTimeNs);
env->SetObjectArrayElement(jJankDataArray, i, jJankData);
env->DeleteLocalRef(jJankData);
}
@@ -2727,7 +2729,7 @@ int register_android_view_SurfaceControl(JNIEnv* env)
jclass jankDataClazz =
FindClassOrDie(env, "android/view/SurfaceControl$JankData");
gJankDataClassInfo.clazz = MakeGlobalRefOrDie(env, jankDataClazz);
- gJankDataClassInfo.ctor = GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JIJ)V");
+ gJankDataClassInfo.ctor = GetMethodIDOrDie(env, gJankDataClassInfo.clazz, "<init>", "(JIJJJ)V");
jclass onJankDataListenerClazz =
FindClassOrDie(env, "android/view/SurfaceControl$OnJankDataListener");
gJankDataListenerClassInfo.clazz = MakeGlobalRefOrDie(env, onJankDataListenerClazz);
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 9a75d3a61dec..54a3b329b542 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -1183,7 +1183,7 @@
<string name="copyUrl" msgid="6229645005987260230">"‏کپی URL"</string>
<string name="selectTextMode" msgid="3225108910999318778">"انتخاب متن"</string>
<string name="undo" msgid="3175318090002654673">"لغو"</string>
- <string name="redo" msgid="7231448494008532233">"بازانجام"</string>
+ <string name="redo" msgid="7231448494008532233">"ازنو انجام دادن"</string>
<string name="autofill" msgid="511224882647795296">"تکمیل خودکار"</string>
<string name="textSelectionCABTitle" msgid="5151441579532476940">"انتخاب متن"</string>
<string name="addToDictionary" msgid="8041821113480950096">"افزودن به واژه‌نامه"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 631270476bb2..6df63d6e8c1a 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -291,7 +291,7 @@
<string name="notification_channel_security" msgid="8516754650348238057">"સુરક્ષા"</string>
<string name="notification_channel_car_mode" msgid="2123919247040988436">"કાર મોડ"</string>
<string name="notification_channel_account" msgid="6436294521740148173">"એકાઉન્ટ સ્થિતિ"</string>
- <string name="notification_channel_developer" msgid="1691059964407549150">"વિકાસકર્તા માટેના સંદેશા"</string>
+ <string name="notification_channel_developer" msgid="1691059964407549150">"ડેવલપર માટેના મેસેજ"</string>
<string name="notification_channel_developer_important" msgid="7197281908918789589">"ડેવલપર માટેના મહત્ત્વપૂર્ણ મેસેજ"</string>
<string name="notification_channel_updates" msgid="7907863984825495278">"અપડેટ્સ"</string>
<string name="notification_channel_network_status" msgid="2127687368725272809">"નેટવર્ક સ્થિતિ"</string>
@@ -400,7 +400,7 @@
<string name="permdesc_readSms" product="tv" msgid="3054753345758011986">"આ ઍપ, તમારા Android TV ડિવાઇસ પર સંગ્રહિત તમામ SMS (ટેક્સ્ટ) મેસેજ વાંચી શકે છે."</string>
<string name="permdesc_readSms" product="default" msgid="774753371111699782">"આ ઍપ, તમારા ફોન પર સંગ્રહિત તમામ SMS (ટેક્સ્ટ) મેસેજ વાંચી શકે છે."</string>
<string name="permlab_receiveWapPush" msgid="4223747702856929056">"ટેક્સ્ટ મેસેજ (WAP) મેળવો"</string>
- <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"એપ્લિકેશનને WAP સંદેશા પ્રાપ્ત કરવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આ પરવાનગીમાં તમને દર્શાવ્યા વિના તમને મોકલેલ સંદેશાઓનું નિરીક્ષણ કરવાની અને કાઢી નાખવાની ક્ષમતાનો સમાવેશ થાય છે."</string>
+ <string name="permdesc_receiveWapPush" msgid="1638677888301778457">"ઍપને WAP મેસેજ મેળવવાની અને તેના પર પ્રક્રિયા કરવાની મંજૂરી આપે છે. આ પરવાનગીમાં તમને દર્શાવ્યા વિના તમને મોકલેલા મેસેજનું નિરીક્ષણ કરવાની અને ડિલીટ કરવાની ક્ષમતાનો સમાવેશ થાય છે."</string>
<string name="permlab_getTasks" msgid="7460048811831750262">"ચાલુ ઍપ્લિકેશનો પુનઃપ્રાપ્ત કરો"</string>
<string name="permdesc_getTasks" msgid="7388138607018233726">"એપ્લિકેશનને વર્તમાનમાં અને તાજેતરમાં ચાલી રહેલ Tasks વિશેની વિગતવાર માહિતી પુનઃપ્રાપ્ત કરવાની મંજૂરી આપે છે. આ એપ્લિકેશનને ઉપકરણ પર કઈ એપ્લિકેશન્સનો ઉપયોગ થાય છે તેના વિશેની માહિતી શોધવાની મંજૂરી આપી શકે છે."</string>
<string name="permlab_manageProfileAndDeviceOwners" msgid="639849495253987493">"પ્રોફાઇલ અને ડિવાઇસ માલિકોને મેનેજ કરો"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 5106f7c58ea7..5593f41523c2 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1721,7 +1721,7 @@
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Verwijderen"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Volume verhogen tot boven het aanbevolen niveau?\n\nAls je langere tijd op hoog volume naar muziek luistert, raakt je gehoor mogelijk beschadigd."</string>
- <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Wil je blijven luisteren op hoog volume?\n\nHet hoofdtelefoonvolume is langer dan de aanbevolen tijd hoog geweest. Dit kan je gehoor beschadigen."</string>
+ <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Wil je blijven luisteren op hoog volume?\n\nHet koptelefoonvolume is langer dan de aanbevolen tijd hoog geweest. Dit kan je gehoor beschadigen."</string>
<string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Hard geluid gedetecteerd\n\nHet hoofdtelefoonvolume is hoger dan aanbevolen. Dit kan je gehoor beschadigen."</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Snelkoppeling toegankelijkheid gebruiken?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Als de snelkoppeling aanstaat, houd je beide volumeknoppen 3 seconden ingedrukt om een toegankelijkheidsfunctie te starten."</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 885be75702a7..805dce5acbd9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1721,7 +1721,7 @@
<string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"Alisin"</string>
<string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"Lakasan ang volume nang lagpas sa inirerekomendang antas?\n\nMaaaring mapinsala ng pakikinig sa malakas na volume sa loob ng mahahabang panahon ang iyong pandinig."</string>
- <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Magpatuloy sa pakikinig nang may malakas na volume?\n\nNaging malakas ang volume nang mas matagal na sa inirerekomenda, at posible nitong mapinsala ang pandinig mo"</string>
+ <string name="csd_dose_reached_warning" product="default" msgid="491875107583931974">"Magpatuloy sa pakikinig nang may malakas na volume?\n\nMalakas ang volume nang mas matagal na sa inirerekomenda, at posible nitong mapinsala ang pandinig mo"</string>
<string name="csd_momentary_exposure_warning" product="default" msgid="7730840903435405501">"Naka-detect ng malakas na tunog\n\nMas malakas ang volume kaysa sa inirerekomenda, at posible nitong mapinsala ang pandinig mo"</string>
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Gagamitin ang Shortcut sa Accessibility?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Kapag naka-on ang shortcut, magsisimula ang isang feature ng pagiging naa-access kapag pinindot ang parehong button ng volume."</string>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f40466610724..606c7fdaa954 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4804,9 +4804,9 @@
</string>
<!-- Title for accessibility edit shortcut selection menu dialog, and dialog is triggered
- from volume key shortcut. [CHAR LIMIT=100] -->
+ from volume keys shortcut. [CHAR LIMIT=100] -->
<string name="accessibility_edit_shortcut_menu_volume_title">Choose features to use with the
- volume key shortcut
+ volume keys shortcut
</string>
<!-- Text for showing the warning to user when uncheck the legacy app item in the accessibility
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index 452ae04c7199..d35bfb7bc1a1 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -131,7 +131,7 @@ easier.
<item name="progressBarStyleSmallInverse">@style/Widget.DeviceDefault.ProgressBar.Small.Inverse</item>
<item name="progressBarStyleLargeInverse">@style/Widget.DeviceDefault.ProgressBar.Large.Inverse</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="seekBarStyle">@style/Widget.DeviceDefault.SeekBar</item>
<item name="ratingBarStyle">@style/Widget.DeviceDefault.RatingBar</item>
<item name="ratingBarStyleIndicator">@style/Widget.DeviceDefault.RatingBar.Indicator</item>
@@ -351,7 +351,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -468,7 +468,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -587,7 +587,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -705,7 +705,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -831,7 +831,7 @@ easier.
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Dialog.Alert</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -948,7 +948,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1064,7 +1064,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1181,7 +1181,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1314,7 +1314,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1432,7 +1432,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1548,7 +1548,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1666,7 +1666,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1783,7 +1783,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -1900,7 +1900,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2017,7 +2017,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2134,7 +2134,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2251,7 +2251,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2373,7 +2373,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2488,7 +2488,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2642,7 +2642,7 @@ easier.
<item name="progressBarStyleSmallInverse">@style/Widget.DeviceDefault.Light.ProgressBar.Small.Inverse</item>
<item name="progressBarStyleLargeInverse">@style/Widget.DeviceDefault.Light.ProgressBar.Large.Inverse</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="seekBarStyle">@style/Widget.DeviceDefault.Light.SeekBar</item>
<item name="ratingBarStyle">@style/Widget.DeviceDefault.Light.RatingBar</item>
<item name="ratingBarStyleIndicator">@style/Widget.DeviceDefault.Light.RatingBar.Indicator</item>
@@ -2858,7 +2858,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -2974,7 +2974,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3091,7 +3091,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3210,7 +3210,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3328,7 +3328,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3452,7 +3452,7 @@ easier.
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3572,7 +3572,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3691,7 +3691,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -3811,7 +3811,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4133,7 +4133,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4254,7 +4254,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4373,7 +4373,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4491,7 +4491,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4608,7 +4608,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4725,7 +4725,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -4840,7 +4840,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5066,7 +5066,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5162,7 +5162,7 @@ easier.
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5280,7 +5280,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5471,7 +5471,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5522,7 +5522,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
@@ -5641,7 +5641,7 @@ easier.
<item name="buttonBarButtonStyle">@style/Widget.DeviceDefault.Button.ButtonBar.AlertDialog</item>
<!-- Progress bar attributes -->
- <item name="colorProgressBackgroundNormal">@color/config_progress_background_tint</item>
+ <item name="colorProgressBackgroundNormal">?attr/materialColorOutline</item>
<item name="progressBarCornerRadius">@dimen/config_progressBarCornerRadius</item>
<!-- Toolbar attributes -->
diff --git a/core/tests/GameManagerTests/Android.bp b/core/tests/GameManagerTests/Android.bp
index 0e3bc6562edb..a252f8b53fab 100644
--- a/core/tests/GameManagerTests/Android.bp
+++ b/core/tests/GameManagerTests/Android.bp
@@ -37,3 +37,10 @@ android_test {
certificate: "platform",
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "FrameworksCoreGameManagerTests_android_app",
+ base: "FrameworksCoreGameManagerTests",
+ test_suites: ["device-tests"],
+ include_filters: ["android.app"],
+}
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index b0e48f1ccd93..99cbf0504be6 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -21,6 +21,7 @@ filegroup {
srcs: [
"DisabledTestApp/src/**/*.java",
"EnabledTestApp/src/**/*.java",
+ "BinderFrozenStateChangeCallbackTestApp/src/**/*.java",
"BinderProxyCountingTestApp/src/**/*.java",
"BinderProxyCountingTestService/src/**/*.java",
"BinderDeathRecipientHelperApp/src/**/*.java",
@@ -138,6 +139,7 @@ android_test {
":BinderDeathRecipientHelperApp1",
":BinderDeathRecipientHelperApp2",
":com.android.cts.helpers.aosp",
+ ":BinderFrozenStateChangeCallbackTestApp",
":BinderProxyCountingTestApp",
":BinderProxyCountingTestService",
":AppThatUsesAppOps",
diff --git a/core/tests/coretests/AndroidTest.xml b/core/tests/coretests/AndroidTest.xml
index 99b73a4afb93..b1f1e2c2db05 100644
--- a/core/tests/coretests/AndroidTest.xml
+++ b/core/tests/coretests/AndroidTest.xml
@@ -22,6 +22,7 @@
<option name="test-file-name" value="FrameworksCoreTests.apk" />
<option name="test-file-name" value="BinderDeathRecipientHelperApp1.apk" />
<option name="test-file-name" value="BinderDeathRecipientHelperApp2.apk" />
+ <option name="test-file-name" value="BinderFrozenStateChangeCallbackTestApp.apk" />
<option name="test-file-name" value="BinderProxyCountingTestApp.apk" />
<option name="test-file-name" value="BinderProxyCountingTestService.apk" />
<option name="test-file-name" value="AppThatUsesAppOps.apk" />
diff --git a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/Android.bp b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/Android.bp
new file mode 100644
index 000000000000..de97ddae6b18
--- /dev/null
+++ b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/Android.bp
@@ -0,0 +1,34 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+}
+
+android_test_helper_app {
+ name: "BinderFrozenStateChangeCallbackTestApp",
+
+ static_libs: ["coretests-aidl"],
+ srcs: ["**/*.java"],
+
+ platform_apis: true,
+ certificate: "platform",
+
+ test_suites: ["device-tests"],
+}
diff --git a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/AndroidManifest.xml b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/AndroidManifest.xml
new file mode 100644
index 000000000000..29c8f5587f3a
--- /dev/null
+++ b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.frameworks.coretests.bfscctestapp">
+
+ <application>
+ <service android:name=".BfsccTestAppCmdService"
+ android:exported="true"/>
+ </application>
+</manifest>
diff --git a/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java
new file mode 100644
index 000000000000..77e8a404a0ff
--- /dev/null
+++ b/core/tests/coretests/BinderFrozenStateChangeCallbackTestApp/src/com/android/frameworks/coretests/bfscctestapp/BfsccTestAppCmdService.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.frameworks.coretests.bfscctestapp;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+import com.android.frameworks.coretests.aidl.IBfsccTestAppCmdService;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+public class BfsccTestAppCmdService extends Service {
+ private IBfsccTestAppCmdService.Stub mBinder = new IBfsccTestAppCmdService.Stub() {
+ private final LinkedBlockingQueue<IBinder.IFrozenStateChangeCallback.State> mNotifications =
+ new LinkedBlockingQueue<>();
+
+ @Override
+ public void listenTo(IBinder binder) throws RemoteException {
+ binder.addFrozenStateChangeCallback(
+ (IBinder who, IBinder.IFrozenStateChangeCallback.State state)
+ -> mNotifications.offer(state));
+ }
+
+ @Override
+ public boolean[] waitAndConsumeNotifications() {
+ List<Boolean> results = new ArrayList<>();
+ try {
+ IBinder.IFrozenStateChangeCallback.State state =
+ mNotifications.poll(5, TimeUnit.SECONDS);
+ if (state != null) {
+ results.add(state == IBinder.IFrozenStateChangeCallback.State.FROZEN);
+ }
+ } catch (InterruptedException e) {
+ return null;
+ }
+ while (mNotifications.size() > 0) {
+ results.add(mNotifications.poll()
+ == IBinder.IFrozenStateChangeCallback.State.FROZEN);
+ }
+ boolean[] convertedResults = new boolean[results.size()];
+ for (int i = 0; i < results.size(); i++) {
+ convertedResults[i] = results.get(i).booleanValue();
+ }
+ return convertedResults;
+ }
+ };
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+}
diff --git a/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java b/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java
index 41b4c69232f4..09d79a69476c 100644
--- a/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java
+++ b/core/tests/coretests/BinderProxyCountingTestService/src/com/android/frameworks/coretests/binderproxycountingtestservice/BinderProxyCountingService.java
@@ -50,4 +50,4 @@ public class BinderProxyCountingService extends Service {
public IBinder onBind(Intent intent) {
return mBinder;
}
-} \ No newline at end of file
+}
diff --git a/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBfsccTestAppCmdService.aidl b/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBfsccTestAppCmdService.aidl
new file mode 100644
index 000000000000..d8d7dc4b72db
--- /dev/null
+++ b/core/tests/coretests/aidl/com/android/frameworks/coretests/aidl/IBfsccTestAppCmdService.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.frameworks.coretests.aidl;
+
+interface IBfsccTestAppCmdService {
+ void listenTo(IBinder binder);
+ boolean[] waitAndConsumeNotifications();
+}
diff --git a/core/tests/coretests/src/android/app/NotificationChannelTest.java b/core/tests/coretests/src/android/app/NotificationChannelTest.java
index c08e42b7179c..e47ef2df48b9 100644
--- a/core/tests/coretests/src/android/app/NotificationChannelTest.java
+++ b/core/tests/coretests/src/android/app/NotificationChannelTest.java
@@ -233,6 +233,33 @@ public class NotificationChannelTest {
}
@Test
+ @EnableFlags({Flags.FLAG_NOTIFICATION_CHANNEL_VIBRATION_EFFECT_API,
+ Flags.FLAG_NOTIF_CHANNEL_CROP_VIBRATION_EFFECTS})
+ public void testLongVibrationFields_canWriteToXml() throws Exception {
+ NotificationChannel channel = new NotificationChannel("id", "name", 3);
+ // populate pattern with contents
+ long[] pattern = new long[65550 / 2];
+ for (int i = 0; i < pattern.length; i++) {
+ pattern[i] = 100;
+ }
+ channel.setVibrationPattern(pattern); // with flag on, also sets effect
+
+ // Send it through parceling & unparceling to simulate being passed through a binder call
+ NotificationChannel fromParcel = writeToAndReadFromParcel(channel);
+ assertThat(fromParcel.getVibrationPattern().length).isEqualTo(
+ NotificationChannel.MAX_VIBRATION_LENGTH);
+
+ // Confirm that this also survives writing to & restoring from XML
+ NotificationChannel result = backUpAndRestore(fromParcel);
+ assertThat(result.getVibrationPattern().length).isEqualTo(
+ NotificationChannel.MAX_VIBRATION_LENGTH);
+ assertThat(result.getVibrationEffect()).isNotNull();
+ assertThat(result.getVibrationEffect()
+ .computeCreateWaveformOffOnTimingsOrNull())
+ .isEqualTo(result.getVibrationPattern());
+ }
+
+ @Test
public void testRestoreSoundUri_customLookup() throws Exception {
Uri uriToBeRestoredUncanonicalized = Uri.parse("content://media/1");
Uri uriToBeRestoredCanonicalized = Uri.parse("content://media/1?title=Song&canonical=1");
diff --git a/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java b/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java
new file mode 100644
index 000000000000..ee2e7e06081e
--- /dev/null
+++ b/core/tests/coretests/src/android/os/BinderFrozenStateChangeNotificationTest.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.platform.test.annotations.IgnoreUnderRavenwood;
+import android.platform.test.ravenwood.RavenwoodRule;
+import android.util.Log;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+
+import com.android.frameworks.coretests.aidl.IBfsccTestAppCmdService;
+import com.android.frameworks.coretests.bdr_helper_app.TestCommsReceiver;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Queue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * Tests functionality of {@link android.os.IBinder.IFrozenStateChangeCallback}.
+ */
+@RunWith(AndroidJUnit4.class)
+@IgnoreUnderRavenwood(blockedBy = ActivityManager.class)
+public class BinderFrozenStateChangeNotificationTest {
+ private static final String TAG = BinderFrozenStateChangeNotificationTest.class.getSimpleName();
+
+ private static final String TEST_PACKAGE_NAME_1 =
+ "com.android.frameworks.coretests.bfscctestapp";
+ private static final String TEST_PACKAGE_NAME_2 =
+ "com.android.frameworks.coretests.bdr_helper_app1";
+ private static final String TEST_APP_CMD_SERVICE =
+ TEST_PACKAGE_NAME_1 + ".BfsccTestAppCmdService";
+
+ private static final int CALLBACK_WAIT_TIMEOUT_SECS = 5;
+
+ private IBfsccTestAppCmdService mBfsccTestAppCmdService;
+ private ServiceConnection mTestAppConnection;
+ private Context mContext;
+ private Handler mHandler;
+
+ @Rule
+ public final RavenwoodRule mRavenwood = new RavenwoodRule();
+
+ @Before
+ public void setUp() throws Exception {
+ mContext = InstrumentationRegistry.getTargetContext();
+ mHandler = new Handler(Looper.getMainLooper());
+ ((ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE)).killUid(
+ mContext.getPackageManager().getPackageUid(TEST_PACKAGE_NAME_1, 0),
+ "Wiping Test Package");
+ mTestAppConnection = bindService();
+ }
+
+ private IBinder getNewRemoteBinder(String testPackage) throws InterruptedException {
+ final CountDownLatch resultLatch = new CountDownLatch(1);
+ final AtomicInteger resultCode = new AtomicInteger(Activity.RESULT_CANCELED);
+ final AtomicReference<Bundle> resultExtras = new AtomicReference<>();
+
+ final Intent intent = new Intent(TestCommsReceiver.ACTION_GET_BINDER)
+ .setClassName(testPackage, TestCommsReceiver.class.getName());
+ mContext.sendOrderedBroadcast(intent, null, new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ resultCode.set(getResultCode());
+ resultExtras.set(getResultExtras(true));
+ resultLatch.countDown();
+ }
+ }, mHandler, Activity.RESULT_CANCELED, null, null);
+
+ assertTrue("Request for binder timed out", resultLatch.await(5, TimeUnit.SECONDS));
+ assertEquals(Activity.RESULT_OK, resultCode.get());
+ return resultExtras.get().getBinder(TestCommsReceiver.EXTRA_KEY_BINDER);
+ }
+
+ private ServiceConnection bindService()
+ throws Exception {
+ final CountDownLatch bindLatch = new CountDownLatch(1);
+ ServiceConnection connection = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ Log.i(TAG, "Service connected");
+ mBfsccTestAppCmdService = IBfsccTestAppCmdService.Stub.asInterface(service);
+ bindLatch.countDown();
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ Log.i(TAG, "Service disconnected");
+ }
+ };
+ mContext.bindService(
+ new Intent().setComponent(
+ new ComponentName(TEST_PACKAGE_NAME_1, TEST_APP_CMD_SERVICE)),
+ connection,
+ Context.BIND_AUTO_CREATE
+ | Context.BIND_NOT_FOREGROUND);
+ if (!bindLatch.await(5, TimeUnit.SECONDS)) {
+ fail("Timed out waiting for the service to bind");
+ }
+ return connection;
+ }
+
+ private void unbindService(ServiceConnection service) {
+ if (service != null) {
+ mContext.unbindService(service);
+ }
+ }
+
+ @Test
+ public void onStateChangeCalled() throws Exception {
+ final LinkedBlockingQueue<Boolean> results = new LinkedBlockingQueue<>();
+ if (createCallback(mBfsccTestAppCmdService.asBinder(), results) == null) {
+ return;
+ }
+ ensureUnfrozenCallback(results);
+ freezeApp1();
+ ensureFrozenCallback(results);
+ unfreezeApp1();
+ ensureUnfrozenCallback(results);
+ }
+
+ @Test
+ public void onStateChangeNotCalledAfterCallbackRemoved() throws Exception {
+ final LinkedBlockingQueue<Boolean> results = new LinkedBlockingQueue<>();
+ IBinder.IFrozenStateChangeCallback callback;
+ if ((callback = createCallback(mBfsccTestAppCmdService.asBinder(), results)) == null) {
+ return;
+ }
+ ensureUnfrozenCallback(results);
+ mBfsccTestAppCmdService.asBinder().removeFrozenStateChangeCallback(callback);
+ freezeApp1();
+ assertEquals("No more callbacks should be invoked.", 0, results.size());
+ }
+
+ @Test
+ public void multipleCallbacks() throws Exception {
+ final LinkedBlockingQueue<Boolean> results1 = new LinkedBlockingQueue<>();
+ final LinkedBlockingQueue<Boolean> results2 = new LinkedBlockingQueue<>();
+ IBinder.IFrozenStateChangeCallback callback1;
+ if ((callback1 = createCallback(mBfsccTestAppCmdService.asBinder(), results1)) == null) {
+ return;
+ }
+ ensureUnfrozenCallback(results1);
+ freezeApp1();
+ ensureFrozenCallback(results1);
+ if (createCallback(mBfsccTestAppCmdService.asBinder(), results2) == null) {
+ return;
+ }
+ ensureFrozenCallback(results2);
+
+ unfreezeApp1();
+ ensureUnfrozenCallback(results1);
+ ensureUnfrozenCallback(results2);
+
+ mBfsccTestAppCmdService.asBinder().removeFrozenStateChangeCallback(callback1);
+ freezeApp1();
+ assertEquals("No more callbacks should be invoked.", 0, results1.size());
+ ensureFrozenCallback(results2);
+ }
+
+ @Test
+ public void onStateChangeCalledWithTheRightBinder() throws Exception {
+ final IBinder binder = mBfsccTestAppCmdService.asBinder();
+ final LinkedBlockingQueue<IBinder> results = new LinkedBlockingQueue<>();
+ IBinder.IFrozenStateChangeCallback callback =
+ (IBinder who, IBinder.IFrozenStateChangeCallback.State state) -> results.offer(who);
+ try {
+ binder.addFrozenStateChangeCallback(callback);
+ } catch (UnsupportedOperationException e) {
+ return;
+ }
+ assertEquals("Callback received the wrong Binder object.",
+ binder, results.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+ freezeApp1();
+ assertEquals("Callback received the wrong Binder object.",
+ binder, results.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+ unfreezeApp1();
+ assertEquals("Callback received the wrong Binder object.",
+ binder, results.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+ }
+
+ @After
+ public void tearDown() {
+ if (mTestAppConnection != null) {
+ mContext.unbindService(mTestAppConnection);
+ }
+ }
+
+ private IBinder.IFrozenStateChangeCallback createCallback(IBinder binder, Queue<Boolean> queue)
+ throws RemoteException {
+ try {
+ final IBinder.IFrozenStateChangeCallback callback =
+ (IBinder who, IBinder.IFrozenStateChangeCallback.State state) ->
+ queue.offer(state == IBinder.IFrozenStateChangeCallback.State.FROZEN);
+ binder.addFrozenStateChangeCallback(callback);
+ return callback;
+ } catch (UnsupportedOperationException e) {
+ return null;
+ }
+ }
+
+ private void ensureFrozenCallback(LinkedBlockingQueue<Boolean> queue)
+ throws InterruptedException {
+ assertEquals(Boolean.TRUE, queue.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+ }
+
+ private void ensureUnfrozenCallback(LinkedBlockingQueue<Boolean> queue)
+ throws InterruptedException {
+ assertEquals(Boolean.FALSE, queue.poll(CALLBACK_WAIT_TIMEOUT_SECS, TimeUnit.SECONDS));
+ }
+
+ private String executeShellCommand(String cmd) throws Exception {
+ return UiDevice.getInstance(
+ InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
+ }
+
+ private void freezeApp1() throws Exception {
+ executeShellCommand("am freeze " + TEST_PACKAGE_NAME_1);
+ }
+
+ private void freezeApp2() throws Exception {
+ executeShellCommand("am freeze " + TEST_PACKAGE_NAME_2);
+ }
+
+ private void unfreezeApp1() throws Exception {
+ executeShellCommand("am unfreeze " + TEST_PACKAGE_NAME_1);
+ }
+
+ private void unfreezeApp2() throws Exception {
+ executeShellCommand("am unfreeze " + TEST_PACKAGE_NAME_2);
+ }
+}
diff --git a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
index 499caf5e12d3..c3a5b19c9442 100644
--- a/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
+++ b/core/tests/coretests/src/com/android/internal/jank/FrameTrackerTest.java
@@ -359,7 +359,7 @@ public class FrameTrackerTest {
tracker.end(FrameTracker.REASON_END_NORMAL);
// Send incomplete callback for 102L
- sendSfFrame(tracker, 102L, JANK_NONE);
+ sendSfFrame(tracker, 4, 102L, JANK_NONE);
// Send janky but complete callbck fo 103L
sendFrame(tracker, 50, JANK_APP_DEADLINE_MISSED, 103L);
@@ -629,7 +629,7 @@ public class FrameTrackerTest {
if (!tracker.mSurfaceOnly) {
sendHwuiFrame(tracker, durationMillis, vsyncId, firstWindowFrame);
}
- sendSfFrame(tracker, vsyncId, jankType);
+ sendSfFrame(tracker, durationMillis, vsyncId, jankType);
}
private void sendHwuiFrame(FrameTracker tracker, long durationMillis, long vsyncId,
@@ -645,11 +645,13 @@ public class FrameTrackerTest {
captor.getValue().run();
}
- private void sendSfFrame(FrameTracker tracker, long vsyncId, @JankType int jankType) {
+ private void sendSfFrame(
+ FrameTracker tracker, long durationMillis, long vsyncId, @JankType int jankType) {
final ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
doNothing().when(tracker).postCallback(captor.capture());
mListenerCapture.getValue().onJankDataAvailable(new JankData[] {
- new JankData(vsyncId, jankType, FRAME_TIME_60Hz)
+ new JankData(vsyncId, jankType, FRAME_TIME_60Hz, FRAME_TIME_60Hz,
+ TimeUnit.MILLISECONDS.toNanos(durationMillis))
});
captor.getValue().run();
}
diff --git a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
index 66de3d7f24f9..397cdcf6acdd 100644
--- a/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BinderDeathDispatcherTest.java
@@ -124,6 +124,16 @@ public class BinderDeathDispatcherTest {
return this;
}
+ @Override
+ public void addFrozenStateChangeCallback(IFrozenStateChangeCallback callback)
+ throws RemoteException {
+ }
+
+ @Override
+ public boolean removeFrozenStateChangeCallback(IFrozenStateChangeCallback callback) {
+ return false;
+ }
+
public void die() {
isAlive = false;
if (mRecipient != null) {
diff --git a/core/tests/hdmitests/Android.bp b/core/tests/hdmitests/Android.bp
index 5f6eaf96a846..e11bc552cf15 100644
--- a/core/tests/hdmitests/Android.bp
+++ b/core/tests/hdmitests/Android.bp
@@ -37,3 +37,10 @@ android_test {
certificate: "platform",
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "HdmiCecTests_hardware_hdmi",
+ base: "HdmiCecTests",
+ test_suites: ["device-tests"],
+ include_filters: ["android.hardware.hdmi"],
+}
diff --git a/core/tests/mockingcoretests/Android.bp b/core/tests/mockingcoretests/Android.bp
index aca52a870655..7fd813a7421a 100644
--- a/core/tests/mockingcoretests/Android.bp
+++ b/core/tests/mockingcoretests/Android.bp
@@ -63,3 +63,13 @@ android_test {
certificate: "platform",
}
+
+test_module_config {
+ name: "FrameworksMockingCoreTests_os_bundlerecyclingtest",
+ base: "FrameworksMockingCoreTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["android.os.BundleRecyclingTest"],
+}
diff --git a/core/tests/timetests/Android.bp b/core/tests/timetests/Android.bp
index 51181a8a7b13..c33d5ee5008b 100644
--- a/core/tests/timetests/Android.bp
+++ b/core/tests/timetests/Android.bp
@@ -23,3 +23,17 @@ android_test {
certificate: "platform",
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "FrameworksTimeCoreTests_android_app",
+ base: "FrameworksTimeCoreTests",
+ test_suites: ["device-tests"],
+ include_filters: ["android.app."],
+}
+
+test_module_config {
+ name: "FrameworksTimeCoreTests_android_service",
+ base: "FrameworksTimeCoreTests",
+ test_suites: ["device-tests"],
+ include_filters: ["android.service."],
+}
diff --git a/core/tests/vibrator/src/android/os/VibrationEffectTest.java b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
index 4f76dd636c30..f5b04ee759a5 100644
--- a/core/tests/vibrator/src/android/os/VibrationEffectTest.java
+++ b/core/tests/vibrator/src/android/os/VibrationEffectTest.java
@@ -430,6 +430,86 @@ public class VibrationEffectTest {
}
@Test
+ public void cropToLength_waveform_underLength() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[]{0, 1, 2},
+ /* repeatIndex= */ -1);
+ VibrationEffect result = effect.cropToLengthOrNull(5);
+
+ assertThat(result).isEqualTo(effect); // unchanged
+ }
+
+ @Test
+ public void cropToLength_waveform_overLength() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
+ /* repeatIndex= */ -1);
+ VibrationEffect result = effect.cropToLengthOrNull(4);
+
+ assertThat(result).isEqualTo(VibrationEffect.createWaveform(
+ new long[]{0, 1, 2, 3},
+ -1));
+ }
+
+ @Test
+ public void cropToLength_waveform_repeating() {
+ // repeating waveforms cannot be truncated
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
+ /* repeatIndex= */ 2);
+ VibrationEffect result = effect.cropToLengthOrNull(3);
+
+ assertThat(result).isNull();
+ }
+
+ @Test
+ public void cropToLength_waveform_withAmplitudes() {
+ VibrationEffect effect = VibrationEffect.createWaveform(
+ /* timings= */ new long[]{0, 1, 2, 3, 4, 5, 6},
+ /* amplitudes= */ new int[]{10, 20, 40, 10, 20, 40, 10},
+ /* repeatIndex= */ -1);
+ VibrationEffect result = effect.cropToLengthOrNull(3);
+
+ assertThat(result).isEqualTo(VibrationEffect.createWaveform(
+ new long[]{0, 1, 2},
+ new int[]{10, 20, 40},
+ -1));
+ }
+
+ @Test
+ public void cropToLength_composed() {
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK)
+ .compose();
+ VibrationEffect result = effect.cropToLengthOrNull(1);
+
+ assertThat(result).isNotNull();
+ assertThat(result).isEqualTo(VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .compose());
+ }
+
+ @Test
+ public void cropToLength_composed_repeating() {
+ VibrationEffect effect = VibrationEffect.startComposition()
+ .addPrimitive(VibrationEffect.Composition.PRIMITIVE_CLICK)
+ .repeatEffectIndefinitely(TEST_ONE_SHOT)
+ .compose();
+ assertThat(effect.cropToLengthOrNull(1)).isNull();
+ }
+
+ @Test
+ @RequiresFlagsEnabled(android.os.vibrator.Flags.FLAG_VENDOR_VIBRATION_EFFECTS)
+ public void cropToLength_vendorEffect() {
+ PersistableBundle vendorData = new PersistableBundle();
+ vendorData.putInt("key", 1);
+ VibrationEffect effect = VibrationEffect.createVendorEffect(vendorData);
+
+ assertThat(effect.cropToLengthOrNull(2)).isNull();
+ }
+
+ @Test
public void getRingtones_noPrebakedRingtones() {
Resources r = mockRingtoneResources(new String[0]);
Context context = mockContext(r);
diff --git a/libs/WindowManager/Shell/AndroidManifest.xml b/libs/WindowManager/Shell/AndroidManifest.xml
index bbbc23e8b922..3b739c3d5817 100644
--- a/libs/WindowManager/Shell/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/AndroidManifest.xml
@@ -23,6 +23,7 @@
<uses-permission android:name="android.permission.ROTATE_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.WAKEUP_SURFACE_FLINGER" />
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
+ <uses-permission android:name="android.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE" />
<application>
<activity
diff --git a/libs/WindowManager/Shell/aconfig/multitasking.aconfig b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
index df1a98c4b417..526ccd55ce3d 100644
--- a/libs/WindowManager/Shell/aconfig/multitasking.aconfig
+++ b/libs/WindowManager/Shell/aconfig/multitasking.aconfig
@@ -25,11 +25,10 @@ flag {
}
flag {
- name: "enable_pip2_implementation"
+ name: "enable_pip2"
namespace: "multitasking"
description: "Enables the new implementation of PiP (PiP2)"
- bug: "290220798"
- is_fixed_read_only: true
+ bug: "311462191"
}
flag {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index ef679dae0157..7b3b2071ef02 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -573,8 +573,14 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
private void startBackNavigation(@NonNull BackTouchTracker touchTracker) {
try {
startLatencyTracking();
+ final BackAnimationAdapter adapter = mEnableAnimations.get()
+ ? mBackAnimationAdapter : null;
+ if (adapter != null && mShellBackAnimationRegistry.hasSupportedAnimatorsChanged()) {
+ adapter.updateSupportedAnimators(
+ mShellBackAnimationRegistry.getSupportedAnimators());
+ }
mBackNavigationInfo = mActivityTaskManager.startBackNavigation(
- mNavigationObserver, mEnableAnimations.get() ? mBackAnimationAdapter : null);
+ mNavigationObserver, adapter);
onBackNavigationInfoReceived(mBackNavigationInfo, touchTracker);
} catch (RemoteException remoteException) {
Log.e(TAG, "Failed to initAnimation", remoteException);
@@ -1180,16 +1186,18 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
}
private void applyFinishOpenTransition() {
+ mOpenTransitionInfo = null;
+ mPrepareOpenTransition = null;
if (mFinishOpenTransaction != null) {
- mFinishOpenTransaction.apply();
+ final SurfaceControl.Transaction t = mFinishOpenTransaction;
mFinishOpenTransaction = null;
+ t.apply();
}
if (mFinishOpenTransitionCallback != null) {
- mFinishOpenTransitionCallback.onTransitionFinished(null);
+ final Transitions.TransitionFinishCallback callback = mFinishOpenTransitionCallback;
mFinishOpenTransitionCallback = null;
+ callback.onTransitionFinished(null);
}
- mOpenTransitionInfo = null;
- mPrepareOpenTransition = null;
}
private void applyAndFinish(@NonNull SurfaceControl.Transaction st,
@@ -1334,6 +1342,9 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
tmpSize = init.getChanges().size();
for (int i = 0; i < tmpSize; ++i) {
final TransitionInfo.Change change = init.getChanges().get(i);
+ if (change.hasFlags(FLAG_IS_WALLPAPER)) {
+ continue;
+ }
if (moveToTop) {
if (isSameChangeTarget(openComponent, openTaskId, openToken, change)) {
change.setFlags(change.getFlags() | FLAG_MOVED_TO_TOP);
@@ -1390,6 +1401,13 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
mergePendingTransitions(info);
}
+ if (info.getType() == TRANSIT_CLOSE_PREPARE_BACK_NAVIGATION
+ && !mCloseTransitionRequested && info.getChanges().isEmpty() && mApps != null) {
+ // Wait for post animation finish
+ finishCallback.onTransitionFinished(null);
+ t.apply();
+ return;
+ }
if (isNotGestureBackTransition(info) || shouldCancelAnimation(info)
|| !mCloseTransitionRequested) {
if (mPrepareOpenTransition != null) {
@@ -1497,15 +1515,28 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
}
}
if (openingLeash != null) {
+ int rootIdx = -1;
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change c = info.getChanges().get(i);
+ if (c.hasFlags(FLAG_IS_WALLPAPER)) {
+ st.setAlpha(c.getLeash(), 1.0f);
+ continue;
+ }
if (TransitionUtil.isOpeningMode(c.getMode())) {
final Point offset = c.getEndRelOffset();
st.setPosition(c.getLeash(), offset.x, offset.y);
st.reparent(c.getLeash(), openingLeash);
st.setAlpha(c.getLeash(), 1.0f);
+ rootIdx = TransitionUtil.rootIndexFor(c, info);
}
}
+ // The root leash and the leash of opening target should actually in the same level,
+ // but since the root leash is created after opening target, it will have higher
+ // layer in surface flinger. Move the root leash to lower level, so it won't affect
+ // the playing animation.
+ if (rootIdx >= 0 && info.getRootCount() > 0) {
+ st.setLayer(info.getRoot(rootIdx).getLeash(), -1);
+ }
}
st.apply();
mFinishOpenTransaction = ft;
@@ -1548,6 +1579,10 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
if (openingLeash != null && closingLeash != null) {
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change c = info.getChanges().get(i);
+ if (c.hasFlags(FLAG_IS_WALLPAPER)) {
+ st.setAlpha(c.getLeash(), 1.0f);
+ continue;
+ }
if (TransitionUtil.isOpeningMode(c.getMode())) {
final Point offset = c.getEndRelOffset();
st.setPosition(c.getLeash(), offset.x, offset.y);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
index 6fafa75e2f70..ae2c7b3adb6b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/ShellBackAnimationRegistry.java
@@ -23,6 +23,8 @@ import android.util.Log;
import android.util.SparseArray;
import android.window.BackNavigationInfo;
+import java.util.ArrayList;
+
/** Registry for all types of default back animations */
public class ShellBackAnimationRegistry {
private static final String TAG = "ShellBackPreview";
@@ -31,6 +33,8 @@ public class ShellBackAnimationRegistry {
private ShellBackAnimation mDefaultCrossActivityAnimation;
private final ShellBackAnimation mCustomizeActivityAnimation;
private final ShellBackAnimation mCrossTaskAnimation;
+ private boolean mSupportedAnimatorsChanged = false;
+ private final ArrayList<Integer> mSupportedAnimators = new ArrayList<>();
public ShellBackAnimationRegistry(
@ShellBackAnimation.CrossActivity @Nullable ShellBackAnimation crossActivityAnimation,
@@ -60,7 +64,7 @@ public class ShellBackAnimationRegistry {
mDefaultCrossActivityAnimation = crossActivityAnimation;
mCustomizeActivityAnimation = customizeActivityAnimation;
mCrossTaskAnimation = crossTaskAnimation;
-
+ updateSupportedAnimators();
// TODO(b/236760237): register dialog close animation when it's completed.
}
@@ -71,6 +75,7 @@ public class ShellBackAnimationRegistry {
if (BackNavigationInfo.TYPE_CROSS_ACTIVITY == type) {
mDefaultCrossActivityAnimation = null;
}
+ updateSupportedAnimators();
}
void unregisterAnimation(@BackNavigationInfo.BackTargetType int type) {
@@ -79,6 +84,24 @@ public class ShellBackAnimationRegistry {
if (BackNavigationInfo.TYPE_CROSS_ACTIVITY == type) {
mDefaultCrossActivityAnimation = null;
}
+ updateSupportedAnimators();
+ }
+
+ private void updateSupportedAnimators() {
+ mSupportedAnimators.clear();
+ for (int i = mAnimationDefinition.size() - 1; i >= 0; --i) {
+ mSupportedAnimators.add(mAnimationDefinition.keyAt(i));
+ }
+ mSupportedAnimatorsChanged = true;
+ }
+
+ boolean hasSupportedAnimatorsChanged() {
+ return mSupportedAnimatorsChanged;
+ }
+
+ ArrayList<Integer> getSupportedAnimators() {
+ mSupportedAnimatorsChanged = false;
+ return mSupportedAnimators;
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
index 5b01a0d87b5e..f03daada4ca0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java
@@ -291,17 +291,11 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
if (hadImeSourceControl != hasImeSourceControl) {
dispatchImeControlTargetChanged(mDisplayId, hasImeSourceControl);
}
+ final boolean hasImeLeash = hasImeSourceControl && imeSourceControl.getLeash() != null;
boolean pendingImeStartAnimation = false;
- boolean canAnimate;
- if (android.view.inputmethod.Flags.refactorInsetsController()) {
- canAnimate = hasImeSourceControl && imeSourceControl.getLeash() != null;
- } else {
- canAnimate = hasImeSourceControl;
- }
-
boolean positionChanged = false;
- if (canAnimate) {
+ if (hasImeLeash) {
if (mAnimation != null) {
final Point lastSurfacePosition = hadImeSourceControl
? mImeSourceControl.getSurfacePosition() : null;
@@ -325,6 +319,13 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
// continue the bar to slide to the end (even without visible IME)
mAnimation.cancel();
}
+
+ // Make mImeSourceControl point to the new control before starting the animation.
+ if (hadImeSourceControl && mImeSourceControl != imeSourceControl) {
+ mImeSourceControl.release(SurfaceControl::release);
+ }
+ mImeSourceControl = imeSourceControl;
+
if (positionChanged) {
if (android.view.inputmethod.Flags.refactorInsetsController()) {
// For showing the IME, the leash has to be available first. Hiding
@@ -338,11 +339,6 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
}
- if (hadImeSourceControl && mImeSourceControl != imeSourceControl) {
- mImeSourceControl.release(SurfaceControl::release);
- }
- mImeSourceControl = imeSourceControl;
-
if (android.view.inputmethod.Flags.refactorInsetsController()) {
if (pendingImeStartAnimation) {
startAnimation(true, true /* forceRestart */);
@@ -465,11 +461,12 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
private void startAnimation(final boolean show, final boolean forceRestart,
@NonNull final ImeTracker.Token statsToken) {
+ if (mImeSourceControl == null || mImeSourceControl.getLeash() == null) {
+ if (DEBUG) Slog.d(TAG, "No leash available, not starting the animation.");
+ return;
+ }
if (android.view.inputmethod.Flags.refactorInsetsController()) {
- if (mImeSourceControl == null || mImeSourceControl.getLeash() == null) {
- if (DEBUG) Slog.d(TAG, "No leash available, not starting the animation.");
- return;
- } else if (!mImeRequestedVisible && show) {
+ if (!mImeRequestedVisible && show) {
// we have a control with leash, but the IME was not requested visible before,
// therefore aborting the show animation.
Slog.e(TAG, "IME was not requested visible, not starting the show animation.");
@@ -478,7 +475,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
}
final InsetsSource imeSource = mInsetsState.peekSource(InsetsSource.ID_IME);
- if (imeSource == null || mImeSourceControl == null) {
+ if (imeSource == null) {
ImeTracker.forLogging().onFailed(statsToken, ImeTracker.PHASE_WM_ANIMATION_CREATE);
return;
}
@@ -515,8 +512,10 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
}
mAnimation.cancel();
}
- final float defaultY = mImeSourceControl.getSurfacePosition().y;
- final float x = mImeSourceControl.getSurfacePosition().x;
+ final InsetsSourceControl animatingControl = new InsetsSourceControl(mImeSourceControl);
+ final SurfaceControl animatingLeash = animatingControl.getLeash();
+ final float defaultY = animatingControl.getSurfacePosition().y;
+ final float x = animatingControl.getSurfacePosition().x;
final float hiddenY = defaultY + mImeFrame.height();
final float shownY = defaultY;
final float startY = show ? hiddenY : shownY;
@@ -538,13 +537,10 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
mAnimation.addUpdateListener(animation -> {
SurfaceControl.Transaction t = mTransactionPool.acquire();
float value = (float) animation.getAnimatedValue();
- if (!android.view.inputmethod.Flags.refactorInsetsController() || (
- mImeSourceControl != null && mImeSourceControl.getLeash() != null)) {
- t.setPosition(mImeSourceControl.getLeash(), x, value);
- final float alpha = (mAnimateAlpha || isFloating)
- ? (value - hiddenY) / (shownY - hiddenY) : 1.f;
- t.setAlpha(mImeSourceControl.getLeash(), alpha);
- }
+ t.setPosition(animatingLeash, x, value);
+ final float alpha = (mAnimateAlpha || isFloating)
+ ? (value - hiddenY) / (shownY - hiddenY) : 1f;
+ t.setAlpha(animatingLeash, alpha);
dispatchPositionChanged(mDisplayId, imeTop(value), t);
t.apply();
mTransactionPool.release(t);
@@ -561,7 +557,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
ValueAnimator valueAnimator = (ValueAnimator) animation;
float value = (float) valueAnimator.getAnimatedValue();
SurfaceControl.Transaction t = mTransactionPool.acquire();
- t.setPosition(mImeSourceControl.getLeash(), x, value);
+ t.setPosition(animatingLeash, x, value);
if (DEBUG) {
Slog.d(TAG, "onAnimationStart d:" + mDisplayId + " top:"
+ imeTop(hiddenY) + "->" + imeTop(shownY)
@@ -573,19 +569,19 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
final float alpha = (mAnimateAlpha || isFloating)
? (value - hiddenY) / (shownY - hiddenY)
: 1.f;
- t.setAlpha(mImeSourceControl.getLeash(), alpha);
+ t.setAlpha(animatingLeash, alpha);
if (mAnimationDirection == DIRECTION_SHOW) {
ImeTracker.forLogging().onProgress(mStatsToken,
ImeTracker.PHASE_WM_ANIMATION_RUNNING);
- t.show(mImeSourceControl.getLeash());
+ t.show(animatingLeash);
}
if (DEBUG_IME_VISIBILITY) {
EventLog.writeEvent(IMF_IME_REMOTE_ANIM_START,
mStatsToken != null ? mStatsToken.getTag() : ImeTracker.TOKEN_NONE,
mDisplayId, mAnimationDirection, alpha, value, endY,
- Objects.toString(mImeSourceControl.getLeash()),
- Objects.toString(mImeSourceControl.getInsetsHint()),
- Objects.toString(mImeSourceControl.getSurfacePosition()),
+ Objects.toString(animatingLeash),
+ Objects.toString(animatingControl.getInsetsHint()),
+ Objects.toString(animatingControl.getSurfacePosition()),
Objects.toString(mImeFrame));
}
t.apply();
@@ -599,31 +595,23 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
EventLog.writeEvent(IMF_IME_REMOTE_ANIM_CANCEL,
mStatsToken != null ? mStatsToken.getTag() : ImeTracker.TOKEN_NONE,
mDisplayId,
- Objects.toString(mImeSourceControl.getInsetsHint()));
+ Objects.toString(animatingControl.getInsetsHint()));
}
}
@Override
public void onAnimationEnd(Animator animation) {
- boolean hasLeash =
- mImeSourceControl != null && mImeSourceControl.getLeash() != null;
if (DEBUG) Slog.d(TAG, "onAnimationEnd " + mCancelled);
SurfaceControl.Transaction t = mTransactionPool.acquire();
if (!mCancelled) {
- if (!android.view.inputmethod.Flags.refactorInsetsController()
- || hasLeash) {
- t.setPosition(mImeSourceControl.getLeash(), x, endY);
- t.setAlpha(mImeSourceControl.getLeash(), 1.f);
- }
+ t.setPosition(animatingLeash, x, endY);
+ t.setAlpha(animatingLeash, 1.f);
}
dispatchEndPositioning(mDisplayId, mCancelled, t);
if (mAnimationDirection == DIRECTION_HIDE && !mCancelled) {
ImeTracker.forLogging().onProgress(mStatsToken,
ImeTracker.PHASE_WM_ANIMATION_RUNNING);
- if (!android.view.inputmethod.Flags.refactorInsetsController()
- || hasLeash) {
- t.hide(mImeSourceControl.getLeash());
- }
+ t.hide(animatingLeash);
removeImeSurface(mDisplayId);
ImeTracker.forLogging().onHidden(mStatsToken);
} else if (mAnimationDirection == DIRECTION_SHOW && !mCancelled) {
@@ -636,13 +624,9 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
EventLog.writeEvent(IMF_IME_REMOTE_ANIM_END,
mStatsToken != null ? mStatsToken.getTag() : ImeTracker.TOKEN_NONE,
mDisplayId, mAnimationDirection, endY,
- Objects.toString(
- mImeSourceControl != null ? mImeSourceControl.getLeash()
- : "null"),
- Objects.toString(mImeSourceControl != null
- ? mImeSourceControl.getInsetsHint() : "null"),
- Objects.toString(mImeSourceControl != null
- ? mImeSourceControl.getSurfacePosition() : "null"),
+ Objects.toString(animatingLeash),
+ Objects.toString(animatingControl.getInsetsHint()),
+ Objects.toString(animatingControl.getSurfacePosition()),
Objects.toString(mImeFrame));
}
t.apply();
@@ -650,6 +634,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
mAnimationDirection = DIRECTION_NONE;
mAnimation = null;
+ animatingControl.release(SurfaceControl::release);
}
});
if (!show) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt
index dcf84d927ad3..7070ce99b24c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/pip/PipUtils.kt
@@ -24,7 +24,6 @@ import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Rect
import android.os.RemoteException
-import android.os.SystemProperties
import android.util.DisplayMetrics
import android.util.Log
import android.util.Pair
@@ -178,9 +177,7 @@ object PipUtils {
"org.chromium.arc", 0)
val isTv = AppGlobals.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK, 0)
- isPip2ExperimentEnabled = SystemProperties.getBoolean(
- "persist.wm_shell.pip2", false) ||
- (Flags.enablePip2Implementation() && !isArc && !isTv)
+ isPip2ExperimentEnabled = Flags.enablePip2() && !isArc && !isTv
}
return isPip2ExperimentEnabled as Boolean
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
index 972b78f6ca9a..6146ecd9ade6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/compatui/CompatUIController.java
@@ -831,7 +831,6 @@ public class CompatUIController implements OnDisplaysChangedListener,
*/
static class CompatUIHintsState {
boolean mHasShownSizeCompatHint;
- boolean mHasShownCameraCompatHint;
boolean mHasShownUserAspectRatioSettingsButtonHint;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
index 39bea1bed447..9af33a84b045 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java
@@ -21,9 +21,12 @@ import static android.content.pm.PackageManager.FEATURE_PC;
import static com.android.wm.shell.shared.ShellSharedConstants.KEY_EXTRA_SHELL_RECENT_TASKS;
+import android.Manifest;
+import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.IApplicationThread;
+import android.app.KeyguardManager;
import android.app.PendingIntent;
import android.content.ComponentName;
import android.content.Context;
@@ -158,6 +161,7 @@ public class RecentTasksController implements TaskStackListenerCallback,
return new IRecentTasksImpl(this);
}
+ @RequiresPermission(Manifest.permission.SUBSCRIBE_TO_KEYGUARD_LOCKED_STATE)
private void onInit() {
mShellController.addExternalInterface(KEY_EXTRA_SHELL_RECENT_TASKS,
this::createExternalInterface, this);
@@ -168,6 +172,8 @@ public class RecentTasksController implements TaskStackListenerCallback,
mTaskStackTransitionObserver.addTaskStackTransitionObserverListener(this,
mMainExecutor);
}
+ mContext.getSystemService(KeyguardManager.class).addKeyguardLockedStateListener(
+ mMainExecutor, isKeyguardLocked -> notifyRecentTasksChanged());
}
void setTransitionHandler(RecentsTransitionHandler handler) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
index 1cbb8bbe5f75..1dad4137a9df 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
@@ -33,7 +33,7 @@ import java.util.Optional;
/**
* Main stage for split-screen mode. When split-screen is active all standard activity types launch
- * on the main stage, except for task that are explicitly pinned to the {@link SideStage}.
+ * on the main stage, except for task that are explicitly pinned to the {@link StageTaskListener}.
* @see StageCoordinator
*/
class MainStage extends StageTaskListener {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
deleted file mode 100644
index 27fd309c09b0..000000000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.splitscreen;
-
-import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.view.SurfaceSession;
-import android.window.WindowContainerToken;
-import android.window.WindowContainerTransaction;
-
-import com.android.internal.protolog.ProtoLog;
-import com.android.launcher3.icons.IconProvider;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.SyncTransactionQueue;
-import com.android.wm.shell.windowdecor.WindowDecorViewModel;
-
-import java.util.Optional;
-
-/**
- * Side stage for split-screen mode. Only tasks that are explicitly pinned to this stage show up
- * here. All other task are launch in the {@link MainStage}.
- *
- * @see StageCoordinator
- */
-class SideStage extends StageTaskListener {
- private static final String TAG = SideStage.class.getSimpleName();
-
- SideStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
- StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
- SurfaceSession surfaceSession, IconProvider iconProvider,
- Optional<WindowDecorViewModel> windowDecorViewModel) {
- super(context, taskOrganizer, displayId, callbacks, syncQueue, surfaceSession,
- iconProvider, windowDecorViewModel);
- }
-
- boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) {
- ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "remove all side stage tasks: childCount=%d toTop=%b",
- mChildrenTaskInfo.size(), toTop);
- if (mChildrenTaskInfo.size() == 0) return false;
- wct.reparentTasks(
- mRootTaskInfo.token,
- null /* newParent */,
- null /* windowingModes */,
- null /* activityTypes */,
- toTop);
- return true;
- }
-
- boolean removeTask(int taskId, WindowContainerToken newParent, WindowContainerTransaction wct) {
- final ActivityManager.RunningTaskInfo task = mChildrenTaskInfo.get(taskId);
- ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "remove side stage task: task=%d exists=%b", taskId,
- task != null);
- if (task == null) return false;
- wct.reparent(task.token, newParent, false /* onTop */);
- return true;
- }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
index a6233dc927a5..526c1d4a179d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java
@@ -50,7 +50,7 @@ public interface SplitScreen {
/**
* The side stage type.
- * @see SideStage
+ * @see StageTaskListener
*/
int STAGE_TYPE_SIDE = 1;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
index cea995ded256..1e6fa2807b9b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java
@@ -32,6 +32,7 @@ import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED_
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__SCREEN_LOCKED_SHOW_ON_TOP;
import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__UNKNOWN_EXIT;
+import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.shared.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.splitscreen.SplitScreenController.ENTER_REASON_DRAG;
@@ -57,6 +58,7 @@ import android.util.Slog;
import com.android.internal.logging.InstanceId;
import com.android.internal.logging.InstanceIdSequence;
+import com.android.internal.protolog.ProtoLog;
import com.android.internal.util.FrameworkStatsLog;
import com.android.wm.shell.shared.split.SplitScreenConstants.SplitPosition;
import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason;
@@ -133,6 +135,11 @@ public class SplitscreenEventLogger {
@SplitPosition int mainStagePosition, int mainStageUid,
@SplitPosition int sideStagePosition, int sideStageUid,
boolean isLandscape) {
+ if (hasStartedSession()) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logEnter: no-op, previous session has not ended");
+ return;
+ }
+
mLoggerSessionId = mIdSequence.newInstanceId();
int enterReason = getLoggerEnterReason(isLandscape);
updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape),
@@ -140,6 +147,14 @@ public class SplitscreenEventLogger {
updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape),
sideStageUid);
updateSplitRatioState(splitRatio);
+
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logEnter: enterReason=%d splitRatio=%f "
+ + "mainStagePosition=%d mainStageUid=%d sideStagePosition=%d "
+ + "sideStageUid=%d isLandscape=%b mEnterSessionId=%d mLoggerSessionId=%d",
+ enterReason, splitRatio, mLastMainStagePosition, mLastMainStageUid,
+ mLastSideStagePosition, mLastSideStageUid, isLandscape,
+ mEnterSessionId != null ? mEnterSessionId.getId() : 0, mLoggerSessionId.getId());
+
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__ENTER,
enterReason,
@@ -212,14 +227,25 @@ public class SplitscreenEventLogger {
@SplitPosition int mainStagePosition, int mainStageUid,
@SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) {
if (mLoggerSessionId == null) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logExit: no-op, mLoggerSessionId is null");
// Ignore changes until we've started logging the session
return;
}
if ((mainStagePosition != SPLIT_POSITION_UNDEFINED
&& sideStagePosition != SPLIT_POSITION_UNDEFINED)
|| (mainStageUid != 0 && sideStageUid != 0)) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN,
+ "logExit: no-op, only main or side stage should be set, not both/none");
throw new IllegalArgumentException("Only main or side stage should be set");
}
+
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logExit: exitReason=%d mainStagePosition=%d"
+ + " mainStageUid=%d sideStagePosition=%d sideStageUid=%d isLandscape=%b"
+ + " mLoggerSessionId=%d", getLoggerExitReason(exitReason),
+ getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape), mainStageUid,
+ getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape), sideStageUid,
+ isLandscape, mLoggerSessionId.getId());
+
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__EXIT,
0 /* enterReason */,
@@ -304,18 +330,25 @@ public class SplitscreenEventLogger {
*/
public void logResize(float splitRatio) {
if (mLoggerSessionId == null) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logResize: no-op, mLoggerSessionId is null");
// Ignore changes until we've started logging the session
return;
}
if (splitRatio <= 0f || splitRatio >= 1f) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN,
+ "logResize: no-op, splitRatio indicates that user is dismissing, not resizing");
// Don't bother reporting resizes that end up dismissing the split, that will be logged
// via the exit event
return;
}
if (!updateSplitRatioState(splitRatio)) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logResize: no-op, split ratio was not changed");
// Ignore if there are no user perceived changes
return;
}
+
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logResize: splitRatio=%f mLoggerSessionId=%d",
+ mLastSplitRatio, mLoggerSessionId.getId());
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__RESIZE,
0 /* enterReason */,
@@ -335,6 +368,7 @@ public class SplitscreenEventLogger {
public void logSwap(@SplitPosition int mainStagePosition, int mainStageUid,
@SplitPosition int sideStagePosition, int sideStageUid, boolean isLandscape) {
if (mLoggerSessionId == null) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logSwap: no-op, mLoggerSessionId is null");
// Ignore changes until we've started logging the session
return;
}
@@ -343,6 +377,11 @@ public class SplitscreenEventLogger {
mainStageUid);
updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape),
sideStageUid);
+
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "logSwap: mainStagePosition=%d mainStageUid=%d "
+ + "sideStagePosition=%d sideStageUid=%d mLoggerSessionId=%d",
+ mLastMainStagePosition, mLastMainStageUid, mLastSideStagePosition,
+ mLastSideStageUid, mLoggerSessionId.getId());
FrameworkStatsLog.write(FrameworkStatsLog.SPLITSCREEN_UI_CHANGED,
FrameworkStatsLog.SPLITSCREEN_UICHANGED__ACTION__SWAP,
0 /* enterReason */,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 8921ceb6175d..f3959cca050b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -155,13 +155,13 @@ import java.util.concurrent.Executor;
/**
* Coordinates the staging (visibility, sizing, ...) of the split-screen {@link MainStage} and
- * {@link SideStage} stages.
+ * other stages.
* Some high-level rules:
- * - The {@link StageCoordinator} is only considered active if the {@link SideStage} contains at
+ * - The {@link StageCoordinator} is only considered active if the other stages contain at
* least one child task.
* - The {@link MainStage} should only have children if the coordinator is active.
* - The {@link SplitLayout} divider is only visible if both the {@link MainStage}
- * and {@link SideStage} are visible.
+ * and other stages are visible.
* - Both stages are put under a single-top root task.
* This rules are mostly implemented in {@link #onStageVisibilityChanged(StageListenerImpl)} and
* {@link #onStageHasChildrenChanged(StageListenerImpl).}
@@ -176,7 +176,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private final MainStage mMainStage;
private final StageListenerImpl mMainStageListener = new StageListenerImpl();
- private final SideStage mSideStage;
+ private final StageTaskListener mSideStage;
private final StageListenerImpl mSideStageListener = new StageListenerImpl();
@SplitPosition
private int mSideStagePosition = SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -338,7 +338,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSurfaceSession,
iconProvider,
mWindowDecorViewModel);
- mSideStage = new SideStage(
+ mSideStage = new StageTaskListener(
mContext,
mTaskOrganizer,
mDisplayId,
@@ -367,7 +367,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@VisibleForTesting
StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
- ShellTaskOrganizer taskOrganizer, MainStage mainStage, SideStage sideStage,
+ ShellTaskOrganizer taskOrganizer, MainStage mainStage, StageTaskListener sideStage,
DisplayController displayController, DisplayImeController displayImeController,
DisplayInsetsController displayInsetsController, SplitLayout splitLayout,
Transitions transitions, TransactionPool transactionPool, ShellExecutor mainExecutor,
@@ -424,6 +424,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return mMainStage.isActive();
}
+ /**
+ * Deactivates main stage by removing the stage from the top level split root (usually when a
+ * task underneath gets removed from the stage root).
+ * @param reparentToTop whether we want to put the stage root back on top
+ */
+ private void deactivateSplit(WindowContainerTransaction wct, boolean reparentToTop) {
+ mMainStage.deactivate(wct, reparentToTop);
+ }
+
/** @return whether this transition-request has the launch-adjacent flag. */
public boolean requestHasLaunchAdjacentFlag(TransitionRequestInfo request) {
final ActivityManager.RunningTaskInfo triggerTask = request.getTriggerTask();
@@ -498,10 +507,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
/**
* {@link MainStage} will be deactivated in {@link #onStageHasChildrenChanged} if the
- * {@link SideStage} no longer has children.
+ * other stages no longer have children.
*/
final boolean result = mSideStage.removeTask(taskId,
- mMainStage.isActive() ? mMainStage.mRootTaskInfo.token : null,
+ isSplitActive() ? mMainStage.mRootTaskInfo.token : null,
wct);
mTaskOrganizer.applyTransaction(wct);
return result;
@@ -618,7 +627,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
// If split screen is not activated, we're expecting to open a pair of apps to split.
- final int extraTransitType = mMainStage.isActive()
+ final int extraTransitType = isSplitActive()
? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
prepareEnterSplitScreen(wct, null /* taskInfo */, position, !mIsDropEntering);
@@ -661,7 +670,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
// If split screen is not activated, we're expecting to open a pair of apps to split.
- final int extraTransitType = mMainStage.isActive()
+ final int extraTransitType = isSplitActive()
? TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE : TRANSIT_SPLIT_SCREEN_PAIR_OPEN;
prepareEnterSplitScreen(wct, null /* taskInfo */, position, !mIsDropEntering);
@@ -793,7 +802,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private void startWithTask(WindowContainerTransaction wct, int mainTaskId,
@Nullable Bundle mainOptions, @PersistentSnapPosition int snapPosition,
@Nullable RemoteTransition remoteTransition, InstanceId instanceId) {
- if (!mMainStage.isActive()) {
+ if (!isSplitActive()) {
// Build a request WCT that will launch both apps such that task 0 is on the main stage
// while task 1 is on the side stage.
mMainStage.activate(wct, false /* reparent */);
@@ -860,7 +869,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
return;
}
- if (!mMainStage.isActive()) {
+ if (!isSplitActive()) {
// Build a request WCT that will launch both apps such that task 0 is on the main stage
// while task 1 is on the side stage.
mMainStage.activate(wct, false /* reparent */);
@@ -1110,7 +1119,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
*/
void onKeyguardStateChanged(boolean active, boolean occludingTaskRunning) {
mKeyguardActive = active;
- if (!mMainStage.isActive()) {
+ if (!isSplitActive()) {
return;
}
ProtoLog.d(WM_SHELL_SPLIT_SCREEN,
@@ -1154,7 +1163,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
* will do a no-op.
*/
void dismissSplitKeepingLastActiveStage(@ExitReason int reason) {
- if (!mMainStage.isActive() || mLastActiveStage == STAGE_TYPE_UNDEFINED) {
+ if (!isSplitActive() || mLastActiveStage == STAGE_TYPE_UNDEFINED) {
// no-op
return;
}
@@ -1177,8 +1186,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private void exitSplitScreen(@Nullable StageTaskListener childrenToTop,
@ExitReason int exitReason) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "exitSplitScreen: mainStageToTop=%b reason=%s active=%b",
- childrenToTop == mMainStage, exitReasonToString(exitReason), mMainStage.isActive());
- if (!mMainStage.isActive()) return;
+ childrenToTop == mMainStage, exitReasonToString(exitReason), isSplitActive());
+ if (!isSplitActive()) return;
final WindowContainerTransaction wct = new WindowContainerTransaction();
applyExitSplitScreen(childrenToTop, wct, exitReason);
@@ -1188,7 +1197,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
WindowContainerTransaction wct, @ExitReason int exitReason) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "applyExitSplitScreen: reason=%s",
exitReasonToString(exitReason));
- if (!mMainStage.isActive() || mIsExiting) return;
+ if (!isSplitActive() || mIsExiting) return;
onSplitScreenExit();
clearSplitPairedInRecents(exitReason);
@@ -1200,7 +1209,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSplitLayout.getInvisibleBounds(mTempRect1);
if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) {
mSideStage.removeAllTasks(wct, false /* toTop */);
- mMainStage.deactivate(wct, false /* toTop */);
+ deactivateSplit(wct, false /* reparentToTop */);
wct.reorder(mRootTaskInfo.token, false /* onTop */);
setRootForceTranslucent(true, wct);
wct.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1);
@@ -1229,7 +1238,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
childrenToTop.fadeOutDecor(() -> {
WindowContainerTransaction finishedWCT = new WindowContainerTransaction();
mIsExiting = false;
- mMainStage.deactivate(finishedWCT, childrenToTop == mMainStage /* toTop */);
+ deactivateSplit(finishedWCT, childrenToTop == mMainStage /* reparentToTop */);
mSideStage.removeAllTasks(finishedWCT, childrenToTop == mSideStage /* toTop */);
finishedWCT.reorder(mRootTaskInfo.token, false /* toTop */);
setRootForceTranslucent(true, finishedWCT);
@@ -1252,7 +1261,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
void dismissSplitScreen(int toTopTaskId, @ExitReason int exitReason) {
- if (!mMainStage.isActive()) return;
+ if (!isSplitActive()) return;
final int stage = getStageOfTask(toTopTaskId);
final WindowContainerTransaction wct = new WindowContainerTransaction();
prepareExitSplitScreen(stage, wct);
@@ -1362,10 +1371,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
*/
void prepareExitSplitScreen(@StageType int stageToTop,
@NonNull WindowContainerTransaction wct) {
- if (!mMainStage.isActive()) return;
+ if (!isSplitActive()) return;
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "prepareExitSplitScreen: stageToTop=%d", stageToTop);
mSideStage.removeAllTasks(wct, stageToTop == STAGE_TYPE_SIDE);
- mMainStage.deactivate(wct, stageToTop == STAGE_TYPE_MAIN);
+ deactivateSplit(wct, stageToTop == STAGE_TYPE_MAIN);
}
private void prepareEnterSplitScreen(WindowContainerTransaction wct) {
@@ -1471,12 +1480,11 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mSkipEvictingMainStageChildren = false;
mSplitRequest = null;
updateRecentTasksSplitPair();
- if (!mLogger.hasStartedSession()) {
- mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
- getMainStagePosition(), mMainStage.getTopChildTaskUid(),
- getSideStagePosition(), mSideStage.getTopChildTaskUid(),
- mSplitLayout.isLeftRightSplit());
- }
+
+ mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
+ getMainStagePosition(), mMainStage.getTopChildTaskUid(),
+ getSideStagePosition(), mSideStage.getTopChildTaskUid(),
+ mSplitLayout.isLeftRightSplit());
}
void getStageBounds(Rect outTopOrLeftBounds, Rect outBottomOrRightBounds) {
@@ -1662,7 +1670,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
mRootTaskInfo = taskInfo;
if (mSplitLayout != null
&& mSplitLayout.updateConfiguration(mRootTaskInfo.configuration)
- && mMainStage.isActive()) {
+ && isSplitActive()) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTaskInfoChanged: task=%d updating",
taskInfo.taskId);
// Clear the divider remote animating flag as the divider will be re-rendered to apply
@@ -1916,7 +1924,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
stageListener == mMainStageListener);
final boolean hasChildren = stageListener.mHasChildren;
final boolean isSideStage = stageListener == mSideStageListener;
- if (!hasChildren && !mIsExiting && mMainStage.isActive()) {
+ if (!hasChildren && !mIsExiting && isSplitActive()) {
if (isSideStage && mMainStageListener.mVisible) {
// Exit to main stage if side stage no longer has children.
mSplitLayout.flingDividerToDismiss(
@@ -1931,7 +1939,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Dismiss split screen in the background once any sides of the split become empty.
exitSplitScreen(null /* childrenToTop */, EXIT_REASON_APP_FINISHED);
}
- } else if (isSideStage && hasChildren && !mMainStage.isActive()) {
+ } else if (isSideStage && hasChildren && !isSplitActive()) {
final WindowContainerTransaction wct = new WindowContainerTransaction();
prepareEnterSplitScreen(wct);
@@ -1952,15 +1960,13 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
clearRequestIfPresented();
updateRecentTasksSplitPair();
- if (!mLogger.hasStartedSession()) {
- if (!mLogger.hasValidEnterSessionId()) {
- mLogger.enterRequested(null /*enterSessionId*/, ENTER_REASON_MULTI_INSTANCE);
- }
- mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
- getMainStagePosition(), mMainStage.getTopChildTaskUid(),
- getSideStagePosition(), mSideStage.getTopChildTaskUid(),
- mSplitLayout.isLeftRightSplit());
+ if (!mLogger.hasStartedSession() && !mLogger.hasValidEnterSessionId()) {
+ mLogger.enterRequested(null /*enterSessionId*/, ENTER_REASON_MULTI_INSTANCE);
}
+ mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
+ getMainStagePosition(), mMainStage.getTopChildTaskUid(),
+ getSideStagePosition(), mSideStage.getTopChildTaskUid(),
+ mSplitLayout.isLeftRightSplit());
}
}
@@ -2146,7 +2152,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
private void onDisplayChange(int displayId, int fromRotation, int toRotation,
@Nullable DisplayAreaInfo newDisplayAreaInfo, WindowContainerTransaction wct) {
- if (displayId != DEFAULT_DISPLAY || !mMainStage.isActive()) {
+ if (displayId != DEFAULT_DISPLAY || !isSplitActive()) {
return;
}
@@ -2441,7 +2447,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
// Not entering or exiting, so just do some house-keeping and validation.
// If we're not in split-mode, just abort so something else can handle it.
- if (!mMainStage.isActive()) return false;
+ if (!isSplitActive()) return false;
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "startAnimation: transition=%d", info.getDebugId());
mSplitLayout.setFreezeDividerWindow(false);
@@ -2683,7 +2689,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
public void onTransitionAnimationComplete() {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onTransitionAnimationComplete");
// If still playing, let it finish.
- if (!mMainStage.isActive() && !mIsExiting) {
+ if (!isSplitActive() && !mIsExiting) {
// Update divider state after animation so that it is still around and positioned
// properly for the animation itself.
mSplitLayout.release();
@@ -3147,7 +3153,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
+ (mSplitLayout != null ? mSplitLayout.isLeftRightSplit() : "null"));
pw.println(innerPrefix + "MainStage");
pw.println(childPrefix + "stagePosition=" + splitPositionToString(getMainStagePosition()));
- pw.println(childPrefix + "isActive=" + mMainStage.isActive());
+ pw.println(childPrefix + "isActive=" + isSplitActive());
mMainStage.dump(pw, childPrefix);
pw.println(innerPrefix + "MainStageListener");
mMainStageListener.dump(pw, childPrefix);
@@ -3267,7 +3273,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onNoLongerSupportMultiWindow(ActivityManager.RunningTaskInfo taskInfo) {
ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "onNoLongerSupportMultiWindow: task=%s", taskInfo);
- if (mMainStage.isActive()) {
+ if (isSplitActive()) {
final boolean isMainStage = mMainStageListener == this;
// If visible, we preserve the app and keep it running. If an app becomes
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 99f3832192e0..459355305280 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -475,6 +475,30 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
});
}
+ // --------
+ // Previously only used in SideStage
+ boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) {
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "remove all side stage tasks: childCount=%d toTop=%b",
+ mChildrenTaskInfo.size(), toTop);
+ if (mChildrenTaskInfo.size() == 0) return false;
+ wct.reparentTasks(
+ mRootTaskInfo.token,
+ null /* newParent */,
+ null /* windowingModes */,
+ null /* activityTypes */,
+ toTop);
+ return true;
+ }
+
+ boolean removeTask(int taskId, WindowContainerToken newParent, WindowContainerTransaction wct) {
+ final ActivityManager.RunningTaskInfo task = mChildrenTaskInfo.get(taskId);
+ ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "remove side stage task: task=%d exists=%b", taskId,
+ task != null);
+ if (task == null) return false;
+ wct.reparent(task.token, newParent, false /* onTop */);
+ return true;
+ }
+
private void sendStatusChanged() {
mCallbacks.onStatusChanged(mRootTaskInfo.isVisible, mChildrenTaskInfo.size() > 0);
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
index 9b27e413b5e4..3d79a1c8cebe 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/HomeTransitionObserver.java
@@ -30,6 +30,7 @@ import android.os.IBinder;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
+import com.android.window.flags.Flags;
import com.android.wm.shell.common.RemoteCallable;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SingleInstanceRemoteListener;
@@ -71,9 +72,17 @@ public class HomeTransitionObserver implements TransitionObserver,
final int mode = change.getMode();
final boolean isBackGesture = change.hasFlags(FLAG_BACK_GESTURE_ANIMATED);
- if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME
- && (TransitionUtil.isOpenOrCloseMode(mode) || isBackGesture)) {
- notifyHomeVisibilityChanged(TransitionUtil.isOpeningType(mode) || isBackGesture);
+ if (taskInfo.getActivityType() == ACTIVITY_TYPE_HOME) {
+ if (Flags.migratePredictiveBackTransition()) {
+ if (!isBackGesture && TransitionUtil.isOpenOrCloseMode(mode)) {
+ notifyHomeVisibilityChanged(TransitionUtil.isOpeningType(mode));
+ }
+ } else {
+ if (TransitionUtil.isOpenOrCloseMode(mode) || isBackGesture) {
+ notifyHomeVisibilityChanged(TransitionUtil.isOpeningType(mode)
+ || isBackGesture);
+ }
+ }
}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index 81251b81e239..aa43c8dab2ad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -114,6 +114,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
private final Choreographer mChoreographer;
private final SyncTransactionQueue mSyncQueue;
private final SplitScreenController mSplitScreenController;
+ private final WindowManagerWrapper mWindowManagerWrapper;
private WindowDecorationViewHolder mWindowDecorViewHolder;
private View.OnClickListener mOnCaptionButtonClickListener;
@@ -188,7 +189,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
taskInfo, taskSurface, handler, bgExecutor, choreographer, syncQueue,
rootTaskDisplayAreaOrganizer, genericLinksParser, SurfaceControl.Builder::new,
SurfaceControl.Transaction::new, WindowContainerTransaction::new,
- SurfaceControl::new, new SurfaceControlViewHostFactory() {},
+ SurfaceControl::new, new WindowManagerWrapper(
+ context.getSystemService(WindowManager.class)),
+ new SurfaceControlViewHostFactory() {},
DefaultMaximizeMenuFactory.INSTANCE, DefaultHandleMenuFactory.INSTANCE,
multiInstanceHelper);
}
@@ -211,6 +214,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
Supplier<SurfaceControl.Transaction> surfaceControlTransactionSupplier,
Supplier<WindowContainerTransaction> windowContainerTransactionSupplier,
Supplier<SurfaceControl> surfaceControlSupplier,
+ WindowManagerWrapper windowManagerWrapper,
SurfaceControlViewHostFactory surfaceControlViewHostFactory,
MaximizeMenuFactory maximizeMenuFactory,
HandleMenuFactory handleMenuFactory,
@@ -229,6 +233,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
mMaximizeMenuFactory = maximizeMenuFactory;
mHandleMenuFactory = handleMenuFactory;
mMultiInstanceHelper = multiInstanceHelper;
+ mWindowManagerWrapper = windowManagerWrapper;
}
/**
@@ -574,7 +579,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
return new AppHandleViewHolder(
mResult.mRootView,
mOnCaptionTouchListener,
- mOnCaptionButtonClickListener
+ mOnCaptionButtonClickListener,
+ mWindowManagerWrapper
);
} else if (mRelayoutParams.mLayoutResId
== R.layout.desktop_mode_app_header) {
@@ -988,6 +994,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
updateGenericLink();
mHandleMenu = mHandleMenuFactory.create(
this,
+ mWindowManagerWrapper,
mRelayoutParams.mLayoutResId,
mAppIconBitmap,
mAppName,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
index 34de94eb3352..748046ebd08d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/HandleMenu.kt
@@ -64,6 +64,7 @@ import com.android.wm.shell.windowdecor.extension.isPinned
*/
class HandleMenu(
private val parentDecor: DesktopModeWindowDecoration,
+ private val windowManagerWrapper: WindowManagerWrapper,
private val layoutResId: Int,
private val appIconBitmap: Bitmap?,
private val appName: CharSequence?,
@@ -178,7 +179,7 @@ class HandleMenu(
handleMenuViewContainer =
if (!taskInfo.isFreeform && Flags.enableAdditionalWindowsAboveStatusBar()) {
AdditionalSystemViewContainer(
- context = context,
+ windowManagerWrapper = windowManagerWrapper,
taskId = taskInfo.taskId,
x = x,
y = y,
@@ -635,6 +636,7 @@ class HandleMenu(
interface HandleMenuFactory {
fun create(
parentDecor: DesktopModeWindowDecoration,
+ windowManagerWrapper: WindowManagerWrapper,
layoutResId: Int,
appIconBitmap: Bitmap?,
appName: CharSequence?,
@@ -652,6 +654,7 @@ interface HandleMenuFactory {
object DefaultHandleMenuFactory : HandleMenuFactory {
override fun create(
parentDecor: DesktopModeWindowDecoration,
+ windowManagerWrapper: WindowManagerWrapper,
layoutResId: Int,
appIconBitmap: Bitmap?,
appName: CharSequence?,
@@ -665,6 +668,7 @@ object DefaultHandleMenuFactory : HandleMenuFactory {
): HandleMenu {
return HandleMenu(
parentDecor,
+ windowManagerWrapper,
layoutResId,
appIconBitmap,
appName,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowManagerWrapper.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowManagerWrapper.kt
new file mode 100644
index 000000000000..5c2ff1b1647c
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowManagerWrapper.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.windowdecor
+
+import android.view.View
+import android.view.WindowManager
+
+/**
+ * A wrapper for [WindowManager] to make view manipulation operations related to window
+ * decors more testable.
+ */
+class WindowManagerWrapper (
+ private val windowManager: WindowManager
+){
+
+ fun addView(v: View, lp: WindowManager.LayoutParams) {
+ windowManager.addView(v, lp)
+ }
+
+ fun removeViewImmediate(v: View) {
+ windowManager.removeViewImmediate(v)
+ }
+
+ fun updateViewLayout(v: View, lp: WindowManager.LayoutParams) {
+ windowManager.updateViewLayout(v, lp)
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
index cadd80e70190..226b0fb2e1a1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainer.kt
@@ -24,13 +24,14 @@ import android.view.LayoutInflater
import android.view.SurfaceControl
import android.view.View
import android.view.WindowManager
+import com.android.wm.shell.windowdecor.WindowManagerWrapper
/**
* An [AdditionalViewContainer] that uses the system [WindowManager] instance. Intended
* for view containers that should be above the status bar layer.
*/
class AdditionalSystemViewContainer(
- context: Context,
+ private val windowManagerWrapper: WindowManagerWrapper,
taskId: Int,
x: Int,
y: Int,
@@ -39,9 +40,20 @@ class AdditionalSystemViewContainer(
flags: Int,
override val view: View
) : AdditionalViewContainer() {
+ val lp: WindowManager.LayoutParams = WindowManager.LayoutParams(
+ width, height, x, y,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
+ flags,
+ PixelFormat.TRANSPARENT
+ ).apply {
+ title = "Additional view container of Task=$taskId"
+ gravity = Gravity.LEFT or Gravity.TOP
+ setTrustedOverlay()
+ }
constructor(
context: Context,
+ windowManagerWrapper: WindowManagerWrapper,
taskId: Int,
x: Int,
y: Int,
@@ -50,7 +62,7 @@ class AdditionalSystemViewContainer(
flags: Int,
@LayoutRes layoutId: Int
) : this(
- context = context,
+ windowManagerWrapper = windowManagerWrapper,
taskId = taskId,
x = x,
y = y,
@@ -61,9 +73,16 @@ class AdditionalSystemViewContainer(
)
constructor(
- context: Context, taskId: Int, x: Int, y: Int, width: Int, height: Int, flags: Int
+ context: Context,
+ windowManagerWrapper: WindowManagerWrapper,
+ taskId: Int,
+ x: Int,
+ y: Int,
+ width: Int,
+ height: Int,
+ flags: Int
) : this(
- context = context,
+ windowManagerWrapper = windowManagerWrapper,
taskId = taskId,
x = x,
y = y,
@@ -73,24 +92,12 @@ class AdditionalSystemViewContainer(
view = View(context)
)
- val windowManager: WindowManager? = context.getSystemService(WindowManager::class.java)
-
init {
- val lp = WindowManager.LayoutParams(
- width, height, x, y,
- WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
- flags,
- PixelFormat.TRANSPARENT
- ).apply {
- title = "Additional view container of Task=$taskId"
- gravity = Gravity.LEFT or Gravity.TOP
- setTrustedOverlay()
- }
- windowManager?.addView(view, lp)
+ windowManagerWrapper.addView(view, lp)
}
override fun releaseView() {
- windowManager?.removeViewImmediate(view)
+ windowManagerWrapper.removeViewImmediate(view)
}
override fun setPosition(t: SurfaceControl.Transaction, x: Float, y: Float) {
@@ -98,6 +105,6 @@ class AdditionalSystemViewContainer(
this.x = x.toInt()
this.y = y.toInt()
}
- windowManager?.updateViewLayout(view, lp)
+ windowManagerWrapper.updateViewLayout(view, lp)
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
index 510032ba4480..dfa5ab415992 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt
@@ -32,6 +32,7 @@ import android.widget.ImageButton
import com.android.window.flags.Flags
import com.android.wm.shell.R
import com.android.wm.shell.shared.animation.Interpolators
+import com.android.wm.shell.windowdecor.WindowManagerWrapper
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystemViewContainer
/**
@@ -41,14 +42,14 @@ import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystem
internal class AppHandleViewHolder(
rootView: View,
onCaptionTouchListener: View.OnTouchListener,
- onCaptionButtonClickListener: OnClickListener
+ onCaptionButtonClickListener: OnClickListener,
+ private val windowManagerWrapper: WindowManagerWrapper
) : WindowDecorationViewHolder(rootView) {
companion object {
private const val CAPTION_HANDLE_ANIMATION_DURATION: Long = 100
}
private lateinit var taskInfo: RunningTaskInfo
- private val windowManager = context.getSystemService(WindowManager::class.java)
private val captionView: View = rootView.requireViewById(R.id.desktop_mode_caption)
private val captionHandle: ImageButton = rootView.requireViewById(R.id.caption_handle)
private val inputManager = context.getSystemService(InputManager::class.java)
@@ -96,11 +97,12 @@ internal class AppHandleViewHolder(
handleWidth: Int,
handleHeight: Int) {
if (!Flags.enableAdditionalWindowsAboveStatusBar()) return
- statusBarInputLayer = AdditionalSystemViewContainer(context, taskInfo.taskId,
- handlePosition.x, handlePosition.y, handleWidth, handleHeight,
+ statusBarInputLayer = AdditionalSystemViewContainer(context, windowManagerWrapper,
+ taskInfo.taskId, handlePosition.x, handlePosition.y, handleWidth, handleHeight,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE)
- val view = statusBarInputLayer?.view
- val lp = view?.layoutParams as WindowManager.LayoutParams
+ val view = statusBarInputLayer?.view ?: error("Unable to find statusBarInputLayer View")
+ val lp = statusBarInputLayer?.lp ?: error("Unable to find statusBarInputLayer" +
+ "LayoutParams")
lp.title = "Handle Input Layer of task " + taskInfo.taskId
lp.setTrustedOverlay()
// Make this window a spy window to enable it to pilfer pointers from the system-wide
@@ -120,7 +122,7 @@ internal class AppHandleViewHolder(
captionHandle.dispatchTouchEvent(event)
true
}
- windowManager.updateViewLayout(view, lp)
+ windowManagerWrapper.updateViewLayout(view, lp)
}
private fun updateStatusBarInputLayer(globalPosition: Point) {
diff --git a/libs/WindowManager/Shell/tests/unittest/Android.bp b/libs/WindowManager/Shell/tests/unittest/Android.bp
index 4d761e18b990..006a4a9ea435 100644
--- a/libs/WindowManager/Shell/tests/unittest/Android.bp
+++ b/libs/WindowManager/Shell/tests/unittest/Android.bp
@@ -94,3 +94,10 @@ android_test {
"com.android.wm.shell.tests",
],
}
+
+test_module_config {
+ name: "WMShellUnitTests_shell_back",
+ base: "WMShellUnitTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.wm.shell.back"],
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
index a8d40db096dd..386253c19c82 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java
@@ -46,6 +46,7 @@ import static java.lang.Integer.MAX_VALUE;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
+import android.app.KeyguardManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -136,6 +137,8 @@ public class RecentTasksControllerTest extends ShellTestCase {
mMainExecutor = new TestShellExecutor();
when(mContext.getPackageManager()).thenReturn(mock(PackageManager.class));
+ when(mContext.getSystemService(KeyguardManager.class))
+ .thenReturn(mock(KeyguardManager.class));
mShellInit = spy(new ShellInit(mMainExecutor));
mShellController = spy(new ShellController(mContext, mShellInit, mShellCommandHandler,
mDisplayInsetsController, mMainExecutor));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
deleted file mode 100644
index 549bd3fcabfb..000000000000
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.wm.shell.splitscreen;
-
-import static android.view.Display.DEFAULT_DISPLAY;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNull;
-import static org.mockito.Mockito.verify;
-
-import android.app.ActivityManager;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-import android.window.WindowContainerTransaction;
-
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.SmallTest;
-
-import com.android.launcher3.icons.IconProvider;
-import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.ShellTestCase;
-import com.android.wm.shell.TestRunningTaskInfoBuilder;
-import com.android.wm.shell.common.SyncTransactionQueue;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.mockito.Spy;
-
-import java.util.Optional;
-
-/** Tests for {@link SideStage} */
-@SmallTest
-@RunWith(AndroidJUnit4.class)
-public class SideStageTests extends ShellTestCase {
- @Mock private ShellTaskOrganizer mTaskOrganizer;
- @Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
- @Mock private SyncTransactionQueue mSyncQueue;
- @Mock private ActivityManager.RunningTaskInfo mRootTask;
- @Mock private SurfaceControl mRootLeash;
- @Mock private IconProvider mIconProvider;
- @Spy private WindowContainerTransaction mWct;
- private SurfaceSession mSurfaceSession = new SurfaceSession();
- private SideStage mSideStage;
-
- @Before
- @UiThreadTest
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mRootTask = new TestRunningTaskInfoBuilder().build();
- mSideStage = new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks,
- mSyncQueue, mSurfaceSession, mIconProvider, Optional.empty());
- mSideStage.onTaskAppeared(mRootTask, mRootLeash);
- }
-
- @Test
- public void testAddTask() {
- final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
-
- mSideStage.addTask(task, mWct);
-
- verify(mWct).reparent(eq(task.token), eq(mRootTask.token), eq(true));
- }
-
- @Test
- public void testRemoveTask() {
- final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
- assertThat(mSideStage.removeTask(task.taskId, null, mWct)).isFalse();
-
- mSideStage.mChildrenTaskInfo.put(task.taskId, task);
- assertThat(mSideStage.removeTask(task.taskId, null, mWct)).isTrue();
- verify(mWct).reparent(eq(task.token), isNull(), eq(false));
- }
-}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
index aa96c45489dd..4de227836104 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java
@@ -74,7 +74,7 @@ public class SplitTestUtils {
final SurfaceControl mRootLeash;
TestStageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
- ShellTaskOrganizer taskOrganizer, MainStage mainStage, SideStage sideStage,
+ ShellTaskOrganizer taskOrganizer, MainStage mainStage, StageTaskListener sideStage,
DisplayController displayController, DisplayImeController imeController,
DisplayInsetsController insetsController, SplitLayout splitLayout,
Transitions transitions, TransactionPool transactionPool,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index abe3dcc1eb80..e16743386489 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -117,7 +117,7 @@ public class SplitTransitionTests extends ShellTestCase {
private final TestShellExecutor mTestShellExecutor = new TestShellExecutor();
private SplitLayout mSplitLayout;
private MainStage mMainStage;
- private SideStage mSideStage;
+ private StageTaskListener mSideStage;
private StageCoordinator mStageCoordinator;
private SplitScreenTransitions mSplitScreenTransitions;
@@ -137,7 +137,7 @@ public class SplitTransitionTests extends ShellTestCase {
StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
mIconProvider, Optional.of(mWindowDecorViewModel)));
mMainStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
- mSideStage = spy(new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
+ mSideStage = spy(new StageTaskListener(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
mIconProvider, Optional.of(mWindowDecorViewModel)));
mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
index 0054cb6ccc8c..c9e1414c39b9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java
@@ -99,7 +99,7 @@ public class StageCoordinatorTests extends ShellTestCase {
@Mock
private MainStage mMainStage;
@Mock
- private SideStage mSideStage;
+ private StageTaskListener mSideStage;
@Mock
private SplitLayout mSplitLayout;
@Mock
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
index 946a7ef7d8c3..acd612eb34d9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
@@ -25,6 +25,7 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeFalse;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -52,6 +53,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
import java.util.Optional;
@@ -76,6 +78,8 @@ public final class StageTaskListenerTests extends ShellTestCase {
private IconProvider mIconProvider;
@Mock
private WindowDecorViewModel mWindowDecorViewModel;
+ @Spy
+ private WindowContainerTransaction mWct;
@Captor
private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor;
private SurfaceSession mSurfaceSession = new SurfaceSession();
@@ -177,4 +181,22 @@ public final class StageTaskListenerTests extends ShellTestCase {
mStageTaskListener.evictAllChildren(wct);
assertFalse(wct.isEmpty());
}
+
+ @Test
+ public void testAddTask() {
+ final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
+ mStageTaskListener.addTask(task, mWct);
+
+ verify(mWct).reparent(eq(task.token), eq(mRootTask.token), eq(true));
+ }
+
+ @Test
+ public void testRemoveTask() {
+ final ActivityManager.RunningTaskInfo task = new TestRunningTaskInfoBuilder().build();
+ assertThat(mStageTaskListener.removeTask(task.taskId, null, mWct)).isFalse();
+
+ mStageTaskListener.mChildrenTaskInfo.put(task.taskId, task);
+ assertThat(mStageTaskListener.removeTask(task.taskId, null, mWct)).isTrue();
+ verify(mWct).reparent(eq(task.token), isNull(), eq(false));
+ }
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
index d2adae181f7b..f51a9608d442 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/transition/HomeTransitionObserverTest.java
@@ -38,6 +38,9 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.RemoteException;
+import android.platform.test.annotations.RequiresFlagsDisabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
import android.window.TransitionInfo.TransitionMode;
@@ -46,6 +49,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import com.android.window.flags.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestShellExecutor;
@@ -57,6 +61,7 @@ import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -70,6 +75,8 @@ import java.util.List;
@RunWith(AndroidJUnit4.class)
public class HomeTransitionObserverTest extends ShellTestCase {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
private final ShellTaskOrganizer mOrganizer = mock(ShellTaskOrganizer.class);
private final TransactionPool mTransactionPool = mock(TransactionPool.class);
private final Context mContext =
@@ -187,6 +194,7 @@ public class HomeTransitionObserverTest extends ShellTestCase {
}
@Test
+ @RequiresFlagsDisabled(Flags.FLAG_MIGRATE_PREDICTIVE_BACK_TRANSITION)
public void testHomeActivityWithBackGestureNotifiesHomeIsVisible() throws RemoteException {
TransitionInfo info = mock(TransitionInfo.class);
TransitionInfo.Change change = mock(TransitionInfo.Change.class);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
index 596adfb98a70..258c86094a36 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java
@@ -173,9 +173,12 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
@Mock
private AppToWebGenericLinksParser mMockGenericLinksParser;
@Mock
+ private WindowManager mMockWindowManager;
+ @Mock
private HandleMenu mMockHandleMenu;
@Mock
private HandleMenuFactory mMockHandleMenuFactory;
+ @Mock
private MultiInstanceHelper mMockMultiInstanceHelper;
@Captor
private ArgumentCaptor<Function1<Boolean, Unit>> mOnMaxMenuHoverChangeListener;
@@ -220,9 +223,10 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
final Display defaultDisplay = mock(Display.class);
doReturn(defaultDisplay).when(mMockDisplayController).getDisplay(Display.DEFAULT_DISPLAY);
doReturn(mInsetsState).when(mMockDisplayController).getInsetsState(anyInt());
- when(mMockHandleMenuFactory.create(any(), anyInt(), any(), any(),
+ when(mMockHandleMenuFactory.create(any(), any(), anyInt(), any(), any(),
any(), anyBoolean(), anyBoolean(), any(), anyInt(), anyInt(), anyInt()))
.thenReturn(mMockHandleMenu);
+ when(mMockMultiInstanceHelper.supportsMultiInstanceSplit(any())).thenReturn(false);
}
@After
@@ -385,6 +389,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
}
@Test
+ @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void updateRelayoutParams_fullscreen_inputChannelNotNeeded() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
@@ -401,6 +406,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
}
@Test
+ @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void updateRelayoutParams_multiwindow_inputChannelNotNeeded() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
@@ -491,7 +497,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
.isTrue();
}
- @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
+ @Test
public void relayout_fullscreenTask_appliesTransactionImmediately() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
@@ -518,7 +524,6 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void relayout_fullscreenTask_doesNotCreateViewHostImmediately() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
@@ -530,7 +535,6 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void relayout_fullscreenTask_postsViewHostCreation() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
@@ -559,7 +563,6 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void relayout_removesExistingHandlerCallback() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
@@ -574,7 +577,6 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
}
@Test
- @DisableFlags(Flags.FLAG_ENABLE_ADDITIONAL_WINDOWS_ABOVE_STATUS_BAR)
public void close_removesExistingHandlerCallback() {
final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
final DesktopModeWindowDecoration spyWindowDecor = spy(createWindowDecoration(taskInfo));
@@ -826,7 +828,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
}
private void verifyHandleMenuCreated(@Nullable Uri uri) {
- verify(mMockHandleMenuFactory).create(any(), anyInt(), any(), any(),
+ verify(mMockHandleMenuFactory).create(any(), any(), anyInt(), any(), any(),
any(), anyBoolean(), anyBoolean(), eq(uri), anyInt(), anyInt(), anyInt());
}
@@ -894,8 +896,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
mMockChoreographer, mMockSyncQueue, mMockRootTaskDisplayAreaOrganizer,
mMockGenericLinksParser, SurfaceControl.Builder::new, mMockTransactionSupplier,
WindowContainerTransaction::new, SurfaceControl::new,
+ new WindowManagerWrapper(mMockWindowManager),
mMockSurfaceControlViewHostFactory, maximizeMenuFactory, mMockHandleMenuFactory,
- mMockMultiInstanceHelper);
+ mMockMultiInstanceHelper);
windowDecor.setCaptionListeners(mMockTouchEventListener, mMockTouchEventListener,
mMockTouchEventListener, mMockTouchEventListener);
windowDecor.setExclusionRegionListener(mMockExclusionRegionListener);
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
index 627dfe718521..100abbbb8332 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/HandleMenuTest.kt
@@ -33,6 +33,7 @@ import android.view.LayoutInflater
import android.view.SurfaceControl
import android.view.SurfaceControlViewHost
import android.view.View
+import android.view.WindowManager
import androidx.core.graphics.toPointF
import androidx.test.filters.SmallTest
import com.android.window.flags.Flags
@@ -77,6 +78,8 @@ class HandleMenuTest : ShellTestCase() {
@Mock
private lateinit var mockDesktopWindowDecoration: DesktopModeWindowDecoration
@Mock
+ private lateinit var mockWindowManager: WindowManager
+ @Mock
private lateinit var onClickListener: View.OnClickListener
@Mock
private lateinit var onTouchListener: View.OnTouchListener
@@ -230,8 +233,9 @@ class HandleMenuTest : ShellTestCase() {
}
else -> error("Invalid windowing mode")
}
- val handleMenu = HandleMenu(mockDesktopWindowDecoration, layoutId, appIcon, appName,
- splitScreenController, shouldShowWindowingPill = true,
+ val handleMenu = HandleMenu(mockDesktopWindowDecoration,
+ WindowManagerWrapper(mockWindowManager),
+ layoutId, appIcon, appName, splitScreenController, shouldShowWindowingPill = true,
shouldShowNewWindowButton = true,
null /* openInBrowserLink */, captionWidth = HANDLE_WIDTH, captionHeight = 50,
captionX = captionX
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainerTest.kt
index 28b4eb6e8ab1..0f52ed7f1c02 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainerTest.kt
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/additionalviewcontainer/AdditionalSystemViewContainerTest.kt
@@ -25,6 +25,7 @@ import android.view.WindowManager
import androidx.test.filters.SmallTest
import com.android.wm.shell.R
import com.android.wm.shell.ShellTestCase
+import com.android.wm.shell.windowdecor.WindowManagerWrapper
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -70,6 +71,7 @@ class AdditionalSystemViewContainerTest : ShellTestCase() {
WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
viewContainer = AdditionalSystemViewContainer(
mockContext,
+ WindowManagerWrapper(mockWindowManager),
TASK_ID,
X,
Y,
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 1930c3d8b9b7..b84990b54bd5 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -288,8 +288,7 @@ public final class MediaRouter2 {
/**
* Returns a proxy MediaRouter2 instance that allows you to control the routing of an app
- * specified by {@code clientPackageName}. Returns {@code null} if the specified package name
- * does not exist.
+ * specified by {@code clientPackageName}.
*
* <p>Proxy MediaRouter2 instances operate differently than regular MediaRouter2 instances:
*
diff --git a/media/tests/AudioPolicyTest/Android.bp b/media/tests/AudioPolicyTest/Android.bp
index 3dc2a0a9fd7c..43b1a355334a 100644
--- a/media/tests/AudioPolicyTest/Android.bp
+++ b/media/tests/AudioPolicyTest/Android.bp
@@ -24,3 +24,11 @@ android_test {
resource_dirs: ["res"],
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "audiopolicytest_audiopolicytest_audiopolicydeathtest_Presubmit",
+ base: "audiopolicytest",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.audiopolicytest.AudioPolicyDeathTest"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
diff --git a/packages/SettingsLib/aconfig/settingslib.aconfig b/packages/SettingsLib/aconfig/settingslib.aconfig
index 2b3862f88c07..34b597ba4486 100644
--- a/packages/SettingsLib/aconfig/settingslib.aconfig
+++ b/packages/SettingsLib/aconfig/settingslib.aconfig
@@ -129,3 +129,13 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "member_device_lea_active_state_sync_fix"
+ namespace: "cross_device_experiences"
+ description: "Gates whether to enable fix for member device active state sync on lea profile"
+ bug: "364201289"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index f739410edea8..a0724b086093 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -130,7 +130,7 @@
<string name="bluetooth_profile_pbap" msgid="2103406516858653017">"સંપર્કો અને કૉલ ઇતિહાસ ઍક્સેસ કરવા દો"</string>
<string name="bluetooth_profile_pbap_summary" msgid="402819589201138227">"માહિતીનો ઉપયોગ કૉલની ઘોષણાઓ અને વધુ બાબતો માટે કરવામાં આવશે"</string>
<string name="bluetooth_profile_pan_nap" msgid="7871974753822470050">"ઇન્ટરનેટ કનેક્શન શેરિંગ"</string>
- <string name="bluetooth_profile_map" msgid="8907204701162107271">"ટેક્સ્ટ સંદેશા"</string>
+ <string name="bluetooth_profile_map" msgid="8907204701162107271">"ટેક્સ્ટ મેસેજ"</string>
<string name="bluetooth_profile_sap" msgid="8304170950447934386">"સિમ ઍક્સેસ"</string>
<string name="bluetooth_profile_a2dp_high_quality" msgid="4739440941324792775">"HD ઑડિયો: <xliff:g id="CODEC_NAME">%1$s</xliff:g>"</string>
<string name="bluetooth_profile_a2dp_high_quality_unknown_codec" msgid="2477639096903834374">"HD ઑડિયો"</string>
diff --git a/packages/SettingsLib/res/values/config.xml b/packages/SettingsLib/res/values/config.xml
index 68b81db1d9c0..3c3de044cc4e 100644
--- a/packages/SettingsLib/res/values/config.xml
+++ b/packages/SettingsLib/res/values/config.xml
@@ -31,4 +31,14 @@
<!-- Control whether status bar should distinguish HSPA data icon form UMTS
data icon on devices -->
<bool name="config_hspa_data_distinguishable">false</bool>
+
+ <!-- Edit User avatar explicit package name -->
+ <string name="config_avatar_picker_package" translatable="false">
+ com.android.avatarpicker
+ </string>
+
+ <!-- Edit User avatar explicit activity class -->
+ <string name="config_avatar_picker_class" translatable="false">
+ com.android.avatarpicker.ui.AvatarPickerActivity
+ </string>
</resources> \ No newline at end of file
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
index cdc3f123eff7..f38e91ac0d8a 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
@@ -32,6 +32,7 @@ import androidx.annotation.Nullable;
import com.android.internal.util.UserIcons;
import com.android.settingslib.drawable.CircleFramedDrawable;
+import com.android.settingslib.R;
import com.android.settingslib.utils.ThreadUtils;
import com.google.common.util.concurrent.FutureCallback;
@@ -132,6 +133,13 @@ public class EditUserPhotoController {
intent.addCategory(Intent.CATEGORY_DEFAULT);
if (Flags.avatarSync()) {
intent.putExtra(EXTRA_IS_USER_NEW, isUserNew);
+ // Fix vulnerability b/341688848 by explicitly set the class name of avatar picker.
+ if (Flags.fixAvatarCrossUserLeak()) {
+ final String packageName =
+ mActivity.getString(R.string.config_avatar_picker_package);
+ final String className = mActivity.getString(R.string.config_avatar_picker_class);
+ intent.setClassName(packageName, className);
+ }
} else {
// SettingsLib is used by multiple apps therefore we need to know out of all apps
// using settingsLib which one is the one we return value to.
diff --git a/packages/SettingsLib/tests/integ/Android.bp b/packages/SettingsLib/tests/integ/Android.bp
index 33d23a3ea16a..48a1af6cb0e8 100644
--- a/packages/SettingsLib/tests/integ/Android.bp
+++ b/packages/SettingsLib/tests/integ/Android.bp
@@ -72,3 +72,10 @@ android_test {
dxflags: ["--multi-dex"],
manifest: "AndroidManifest.xml",
}
+
+test_module_config {
+ name: "SettingsLibTests_settingslib_users",
+ base: "SettingsLibTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.settingslib.users."],
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index ec50323dd91d..e85ba453945b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2173,8 +2173,7 @@ class DatabaseHelper extends SQLiteOpenHelper {
(1 << AudioManager.STREAM_NOTIFICATION) |
(1 << AudioManager.STREAM_SYSTEM) |
(1 << AudioManager.STREAM_SYSTEM_ENFORCED);
- if (!mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_voice_capable)) {
+ if (!getTelephonyManager().isVoiceCapable()) {
ringerModeAffectedStreams |= (1 << AudioManager.STREAM_MUSIC);
}
loadSetting(stmt, Settings.System.MODE_RINGER_STREAMS_AFFECTED,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
index 121bd3e6e771..bfbf41dc87ce 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DeviceConfigService.java
@@ -99,6 +99,12 @@ public final class DeviceConfigService extends Binder {
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ pw.print("SyncDisabledForTests: ");
+ MyShellCommand.getSyncDisabledForTests(pw, pw);
+
+ pw.print("Is mainline: ");
+ pw.println(UpdatableDeviceConfigServiceReadiness.shouldStartUpdatableService());
+
final IContentProvider iprovider = mProvider.getIContentProvider();
pw.println("DeviceConfig flags:");
for (String line : MyShellCommand.listAll(iprovider)) {
@@ -232,6 +238,17 @@ public final class DeviceConfigService extends Binder {
return Binder.getCallingUid() == Process.ROOT_UID;
}
+ private static int getSyncDisabledForTests(PrintWriter pOut, PrintWriter pErr) {
+ int syncDisabledModeInt = DeviceConfig.getSyncDisabledMode();
+ String syncDisabledModeString = formatSyncDisabledMode(syncDisabledModeInt);
+ if (syncDisabledModeString == null) {
+ pErr.println("Unknown mode: " + syncDisabledModeInt);
+ return -1;
+ }
+ pOut.println(syncDisabledModeString);
+ return 0;
+ }
+
public static HashMap<String, String> getAllFlags(IContentProvider provider) {
HashMap<String, String> allFlags = new HashMap<String, String>();
for (DeviceConfig.Properties properties : DeviceConfig.getAllProperties()) {
@@ -597,14 +614,7 @@ public final class DeviceConfigService extends Binder {
DeviceConfig.setSyncDisabledMode(syncDisabledModeArg);
break;
case GET_SYNC_DISABLED_FOR_TESTS:
- int syncDisabledModeInt = DeviceConfig.getSyncDisabledMode();
- String syncDisabledModeString = formatSyncDisabledMode(syncDisabledModeInt);
- if (syncDisabledModeString == null) {
- perr.println("Unknown mode: " + syncDisabledModeInt);
- return -1;
- }
- pout.println(syncDisabledModeString);
- break;
+ return getSyncDisabledForTests(pout, perr);
default:
perr.println("Unspecified command");
return -1;
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
index c60eb61c57eb..fb1f715bc68f 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
@@ -41,6 +41,7 @@ android_app {
"SettingsLibDisplayUtils",
"SettingsLibSettingsTheme",
"com_android_a11y_menu_flags_lib",
+ "//frameworks/libs/systemui:view_capture",
],
optimize: {
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
index fd9a9c634a36..3c73eca732a1 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/grid_item.xml
@@ -3,8 +3,7 @@
android:id="@+id/shortcutItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingTop="@dimen/grid_item_padding"
- android:paddingBottom="@dimen/grid_item_padding"
+ android:padding="@dimen/grid_item_padding"
android:gravity="center">
<ImageButton
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml
index 6be765528028..adaa6551eeae 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/res/layout/paged_menu.xml
@@ -1,25 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
-<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/row_width"
android:layout_height="match_parent"
- android:id="@+id/coordinatorLayout"
- android:background="@drawable/view_background"
- >
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="vertical"
+ android:background="@drawable/view_background">
- <androidx.viewpager2.widget.ViewPager2
- android:id="@+id/view_pager"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingTop="@dimen/table_margin_top"
- android:paddingBottom="@dimen/a11ymenu_layout_margin"
- android:layout_gravity="center"
- android:gravity="center"
- />
+ <androidx.viewpager2.widget.ViewPager2
+ android:id="@+id/view_pager"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:paddingTop="@dimen/table_margin_top"
+ android:paddingBottom="@dimen/a11ymenu_layout_margin"
+ android:gravity="center"
+ />
- <include layout="@layout/footerlayout_switch_page"/>
- </LinearLayout>
-</androidx.coordinatorlayout.widget.CoordinatorLayout>
+ <include layout="@layout/footerlayout_switch_page"/>
+</LinearLayout>
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java
index 78fbf01a1644..136a4ed8626b 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuFooter.java
@@ -55,6 +55,8 @@ public class A11yMenuFooter {
private View mBottomListDivider;
private final A11yMenuFooterCallBack mCallBack;
private final ViewGroup mMenuLayout;
+ private ViewGroup mFooterContainer;
+ private int mFooterContainerBaseHeight = 0;
private int mRightToLeftDirection = LAYOUT_DIRECTION_LTR;
public A11yMenuFooter(ViewGroup menuLayout, A11yMenuFooterCallBack callBack) {
@@ -74,6 +76,15 @@ public class A11yMenuFooter {
? mPageRightBtn : mPageLeftBtn;
}
+ void adjustFooterToDensityScale(float densityScale) {
+ mFooterContainer.getLayoutParams().height =
+ (int) (mFooterContainerBaseHeight / densityScale);
+ }
+
+ int getHeight() {
+ return mFooterContainer.getLayoutParams().height;
+ }
+
/** Sets right to left direction of footer. */
public void updateRightToLeftDirection(Configuration configuration) {
mRightToLeftDirection = TextUtils.getLayoutDirectionFromLocale(
@@ -85,8 +96,9 @@ public class A11yMenuFooter {
}
private void configureFooterLayout(ViewGroup menuLayout) {
- ViewGroup footerContainer = menuLayout.findViewById(R.id.footerlayout);
- footerContainer.setVisibility(View.VISIBLE);
+ mFooterContainer = menuLayout.findViewById(R.id.footerlayout);
+ mFooterContainer.setVisibility(View.VISIBLE);
+ mFooterContainerBaseHeight = mFooterContainer.getLayoutParams().height;
mPageLeftBtn = menuLayout.findViewById(R.id.menu_left_button);
mPageRightBtn = menuLayout.findViewById(R.id.menu_right_button);
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
index 448472d1b6e4..3db61a58c7a3 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
@@ -22,6 +22,8 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.View.ACCESSIBILITY_LIVE_REGION_POLITE;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
+import static com.android.app.viewcapture.ViewCaptureFactory.getViewCaptureAwareWindowManagerInstance;
+
import static java.lang.Math.max;
import android.animation.Animator;
@@ -53,6 +55,7 @@ import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.UiContext;
+import com.android.app.viewcapture.ViewCaptureAwareWindowManager;
import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
import com.android.systemui.accessibility.accessibilitymenu.Flags;
import com.android.systemui.accessibility.accessibilitymenu.R;
@@ -143,7 +146,9 @@ public class A11yMenuOverlayLayout {
final Display display = mDisplayManager.getDisplay(DEFAULT_DISPLAY);
final Context uiContext = mService.createWindowContext(
display, TYPE_ACCESSIBILITY_OVERLAY, /* options= */null);
- final WindowManager windowManager = uiContext.getSystemService(WindowManager.class);
+ final ViewCaptureAwareWindowManager windowManager =
+ getViewCaptureAwareWindowManagerInstance(uiContext,
+ com.android.systemui.Flags.enableViewCaptureTracing());
mLayout = new A11yMenuFrameLayout(uiContext);
updateLayoutPosition(uiContext);
inflateLayoutAndSetOnTouchListener(mLayout, uiContext);
@@ -158,8 +163,8 @@ public class A11yMenuOverlayLayout {
public void clearLayout() {
if (mLayout != null) {
- WindowManager windowManager =
- mLayout.getContext().getSystemService(WindowManager.class);
+ ViewCaptureAwareWindowManager windowManager = getViewCaptureAwareWindowManagerInstance(
+ mLayout.getContext(), com.android.systemui.Flags.enableViewCaptureTracing());
if (windowManager != null) {
windowManager.removeView(mLayout);
}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
index a29ce82dc132..35f124874597 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuViewPager.java
@@ -28,6 +28,7 @@ import android.view.WindowManager;
import android.view.WindowMetrics;
import android.widget.GridView;
+import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
@@ -163,7 +164,9 @@ public class A11yMenuViewPager {
mA11yMenuShortcutList = shortcutDataList;
initViewPager();
initChildPage();
- mA11yMenuFooter = new A11yMenuFooter(a11yMenuLayout, mFooterCallbacks);
+ if (mA11yMenuFooter == null) {
+ mA11yMenuFooter = new A11yMenuFooter(a11yMenuLayout, mFooterCallbacks);
+ }
mA11yMenuFooter.updateRightToLeftDirection(
a11yMenuLayout.getResources().getConfiguration());
updateFooterState();
@@ -233,11 +236,17 @@ public class A11yMenuViewPager {
return;
}
- if (mGridPageList.isEmpty()) {
+ if (mViewPagerAdapter.getItemCount() == 0) {
return;
}
- GridView firstGridView = mGridPageList.get(0);
+ RecyclerView.ViewHolder viewHolder =
+ ((RecyclerView) mViewPager.getChildAt(0))
+ .findViewHolderForAdapterPosition(0);
+ if (viewHolder == null) {
+ return;
+ }
+ GridView firstGridView = (GridView) viewHolder.itemView;
if (firstGridView == null
|| firstGridView.getChildAt(0) == null) {
return;
@@ -280,10 +289,8 @@ public class A11yMenuViewPager {
DisplayMetrics displayMetrics = mService.getResources().getDisplayMetrics();
float densityScale = (float) displayMetrics.densityDpi
/ DisplayMetrics.DENSITY_DEVICE_STABLE;
- View footerLayout = mA11yMenuLayout.findViewById(R.id.footerlayout);
// Keeps footer window height unchanged no matter the density is changed.
- footerLayout.getLayoutParams().height =
- (int) (footerLayout.getLayoutParams().height / densityScale);
+ mA11yMenuFooter.adjustFooterToDensityScale(densityScale);
// Adjust the view pager height for system bar and display cutout insets.
WindowManager windowManager = mA11yMenuLayout.getContext()
.getSystemService(WindowManager.class);
@@ -292,20 +299,18 @@ public class A11yMenuViewPager {
WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
viewPagerHeight =
windowMetric.getBounds().height()
- - footerLayout.getLayoutParams().height
+ - mA11yMenuFooter.getHeight()
- windowInsets.bottom;
// Sets vertical interval between grid items.
int interval =
(viewPagerHeight - topMargin - defaultMargin
- (rowsInGridView * gridItemHeight))
/ (rowsInGridView + 1);
- for (GridView gridView : mGridPageList) {
- gridView.setVerticalSpacing(interval);
- }
+ mViewPagerAdapter.setVerticalSpacing(interval);
// Sets padding to view pager.
final int finalMarginTop = interval + topMargin;
- mViewPager.setPadding(defaultMargin, finalMarginTop, defaultMargin, defaultMargin);
+ mViewPager.setPadding(0, finalMarginTop, 0, defaultMargin);
}
final ViewGroup.LayoutParams layoutParams = mViewPager.getLayoutParams();
layoutParams.height = viewPagerHeight;
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
index 152ff68b8a07..4b14e51ab8dd 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/ViewPagerAdapter.java
@@ -36,11 +36,19 @@ class ViewPagerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
/** List of shortcuts, split into sub lists per page */
private List<List<A11yMenuShortcut>> mShortcutList;
private final AccessibilityMenuService mService;
+ private int mVerticalSpacing = 0;
ViewPagerAdapter(AccessibilityMenuService service) {
mService = service;
}
+ public void setVerticalSpacing(int spacing) {
+ if (mVerticalSpacing != spacing) {
+ mVerticalSpacing = spacing;
+ notifyDataSetChanged();
+ }
+ }
+
public void set(List<List<A11yMenuShortcut>> tList) {
mShortcutList = tList;
notifyDataSetChanged();
@@ -61,6 +69,7 @@ class ViewPagerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
GridView gridView = (GridView) holder.itemView;
gridView.setNumColumns(A11yMenuViewPager.GridViewParams.getGridColumnCount(mService));
gridView.setAdapter(adapter);
+ gridView.setVerticalSpacing(mVerticalSpacing);
}
@Override
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig
index cf13621c2c1b..be748dafa196 100644
--- a/packages/SystemUI/aconfig/systemui.aconfig
+++ b/packages/SystemUI/aconfig/systemui.aconfig
@@ -637,10 +637,13 @@ flag {
}
flag {
- name: "smartspace_remoteviews_rendering"
+ name: "smartspace_remoteviews_rendering_fix"
namespace: "systemui"
description: "Indicate Smartspace RemoteViews rendering"
bug: "326292691"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
}
flag {
@@ -651,6 +654,13 @@ flag {
}
flag {
+ name: "smartspace_viewpager2"
+ namespace: "systemui"
+ description: "Use viewpager2 in Smartspace"
+ bug: "259566300"
+}
+
+flag {
name: "pin_input_field_styled_focus_state"
namespace: "systemui"
description: "Enables styled focus states on pin input field if keyboard is connected"
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
index 9f78d69505de..34eafdee9c76 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerContent.kt
@@ -102,6 +102,7 @@ import com.android.systemui.bouncer.ui.viewmodel.PatternBouncerViewModel
import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
import com.android.systemui.common.shared.model.Text.Companion.loadText
import com.android.systemui.common.ui.compose.Icon
+import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.fold.ui.composable.foldPosture
import com.android.systemui.fold.ui.helper.FoldPosture
import com.android.systemui.res.R
@@ -259,8 +260,11 @@ private fun SplitLayout(
viewModel = viewModel.message,
modifier = Modifier.align(Alignment.TopCenter),
)
-
- OutputArea(viewModel = viewModel, modifier = Modifier.align(Alignment.Center))
+ OutputArea(
+ viewModel = viewModel,
+ modifier =
+ Modifier.align(Alignment.Center).sysuiResTag("bouncer_text_entry")
+ )
ActionArea(
viewModel = viewModel,
@@ -310,8 +314,11 @@ private fun SplitLayout(
StatusMessage(
viewModel = viewModel.message,
)
-
- OutputArea(viewModel = viewModel, modifier = Modifier.padding(top = 24.dp))
+ OutputArea(
+ viewModel = viewModel,
+ modifier =
+ Modifier.padding(top = 24.dp).sysuiResTag("bouncer_text_entry")
+ )
}
}
else -> Unit
@@ -417,10 +424,9 @@ private fun BesideUserSwitcherLayout(
StatusMessage(
viewModel = viewModel.message,
)
-
OutputArea(
viewModel = viewModel,
- modifier = Modifier.padding(top = 24.dp).testTag("OutputArea")
+ modifier = Modifier.padding(top = 24.dp).sysuiResTag("bouncer_text_entry")
)
}
},
@@ -485,7 +491,6 @@ private fun BelowUserSwitcherLayout(
StatusMessage(
viewModel = viewModel.message,
)
-
OutputArea(viewModel = viewModel, modifier = Modifier.padding(top = 24.dp))
InputArea(
@@ -654,17 +659,16 @@ private fun OutputArea(
) {
val authMethodViewModel: AuthMethodBouncerViewModel? by
viewModel.authMethodViewModel.collectAsStateWithLifecycle()
-
when (val nonNullViewModel = authMethodViewModel) {
is PinBouncerViewModel ->
PinInputDisplay(
viewModel = nonNullViewModel,
- modifier = modifier,
+ modifier = modifier.sysuiResTag("bouncer_text_entry")
)
is PasswordBouncerViewModel ->
PasswordBouncer(
viewModel = nonNullViewModel,
- modifier = modifier,
+ modifier = modifier.sysuiResTag("bouncer_text_entry")
)
else -> Unit
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
index c5bb33c414b1..7fb88e8d1fcc 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
@@ -27,8 +27,8 @@ import com.android.compose.animation.scene.SceneScope
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.bouncer.ui.BouncerDialogFactory
-import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneActionsViewModel
import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
+import com.android.systemui.bouncer.ui.viewmodel.BouncerUserActionsViewModel
import com.android.systemui.compose.modifiers.sysuiResTag
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.ExclusiveActivatable
@@ -54,18 +54,17 @@ object Bouncer {
class BouncerScene
@Inject
constructor(
- private val actionsViewModelFactory: BouncerSceneActionsViewModel.Factory,
+ private val actionsViewModelFactory: BouncerUserActionsViewModel.Factory,
private val contentViewModelFactory: BouncerSceneContentViewModel.Factory,
private val dialogFactory: BouncerDialogFactory,
) : ExclusiveActivatable(), Scene {
override val key = Scenes.Bouncer
- private val actionsViewModel: BouncerSceneActionsViewModel by lazy {
+ private val actionsViewModel: BouncerUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
index 4ec0d999ea03..480e4e47ecf0 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
@@ -93,11 +93,15 @@ fun PinPad(
}
}
+ // set the focus, so adb can send the key events for testing.
+ val focusRequester = FocusRequester()
+ LaunchedEffect(Unit) { focusRequester.requestFocus() }
+
VerticalGrid(
columns = columns,
verticalSpacing = verticalSpacing,
horizontalSpacing = calculateHorizontalSpacingBetweenColumns(gridWidth = 300.dp),
- modifier = modifier,
+ modifier = modifier.focusRequester(focusRequester)
) {
repeat(9) { index ->
DigitButton(
@@ -285,26 +289,26 @@ private fun PinPadButton(
Box(
contentAlignment = Alignment.Center,
modifier =
- modifier
- .focusRequester(FocusRequester.Default)
- .focusable()
- .sizeIn(maxWidth = pinButtonMaxSize, maxHeight = pinButtonMaxSize)
- .aspectRatio(1f)
- .drawBehind {
- drawRoundRect(
- color = containerColor,
- cornerRadius = CornerRadius(cornerRadius.toPx()),
- )
- }
- .clip(CircleShape)
- .thenIf(isEnabled) {
- Modifier.combinedClickable(
- interactionSource = interactionSource,
- indication = indication,
- onClick = onClicked,
- onLongClick = onLongPressed
- )
- },
+ modifier
+ .focusRequester(FocusRequester.Default)
+ .focusable()
+ .sizeIn(maxWidth = pinButtonMaxSize, maxHeight = pinButtonMaxSize)
+ .aspectRatio(1f)
+ .drawBehind {
+ drawRoundRect(
+ color = containerColor,
+ cornerRadius = CornerRadius(cornerRadius.toPx()),
+ )
+ }
+ .clip(CircleShape)
+ .thenIf(isEnabled) {
+ Modifier.combinedClickable(
+ interactionSource = interactionSource,
+ indication = indication,
+ onClick = onClicked,
+ onLongClick = onLongPressed
+ )
+ },
) {
content(contentColor::value)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinInputDisplay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinInputDisplay.kt
index 465eade4e169..ba885f7da2cf 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinInputDisplay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinInputDisplay.kt
@@ -34,8 +34,10 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
@@ -351,14 +353,17 @@ private class PinInputRow(
@Composable
fun Content(modifier: Modifier) {
- Row(
- modifier =
+
+ // Wrap PIN entry in a Box so it is visible to accessibility (even if empty).
+ Box(modifier = modifier.fillMaxWidth().wrapContentHeight()) {
+ Row(
modifier
.heightIn(min = shapeAnimations.shapeSize)
// Pins overflowing horizontally should still be shown as scrolling.
- .wrapContentSize(unbounded = true),
- ) {
- entries.forEach { entry -> key(entry.digit) { entry.Content() } }
+ .wrapContentSize(unbounded = true)
+ ) {
+ entries.forEach { entry -> key(entry.digit) { entry.Content() } }
+ }
}
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
index f658169a24ff..8b6de6ab22f3 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalScene.kt
@@ -49,10 +49,10 @@ constructor(
) : ExclusiveActivatable(), Scene {
override val key = Scenes.Communal
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- MutableStateFlow<Map<UserAction, UserActionResult>>(
+ override val userActions: Flow<Map<UserAction, UserActionResult>> =
+ MutableStateFlow(
mapOf(
- Swipe(SwipeDirection.End) to UserActionResult(Scenes.Lockscreen),
+ Swipe(SwipeDirection.End) to Scenes.Lockscreen,
)
)
.asStateFlow()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
index 5f600d3002cc..c7c29f9fdb7c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/LockscreenScene.kt
@@ -24,7 +24,7 @@ import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.animateContentFloatAsState
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneActionsViewModel
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenUserActionsViewModel
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.scene.shared.model.Scenes
@@ -38,17 +38,16 @@ import kotlinx.coroutines.flow.Flow
class LockscreenScene
@Inject
constructor(
- actionsViewModelFactory: LockscreenSceneActionsViewModel.Factory,
+ actionsViewModelFactory: LockscreenUserActionsViewModel.Factory,
private val lockscreenContent: Lazy<LockscreenContent>,
) : ExclusiveActivatable(), Scene {
override val key = Scenes.Lockscreen
- private val actionsViewModel: LockscreenSceneActionsViewModel by lazy {
+ private val actionsViewModel: LockscreenUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
index e4c611ee0eb2..a22beccf3448 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeOverlay.kt
@@ -23,6 +23,8 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.android.compose.animation.scene.ContentScope
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.rememberViewModel
@@ -39,6 +41,7 @@ import com.android.systemui.statusbar.phone.ui.StatusBarIconController
import com.android.systemui.statusbar.phone.ui.TintedIconManager
import dagger.Lazy
import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
@SysUISingleton
class NotificationsShadeOverlay
@@ -59,6 +62,8 @@ constructor(
actionsViewModelFactory.create()
}
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
+
override suspend fun activate(): Nothing {
actionsViewModel.activate()
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt
index ea3f066960c1..1f4cd0473086 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/notifications/ui/composable/NotificationsShadeScene.kt
@@ -29,7 +29,7 @@ import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.rememberViewModel
-import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneActionsViewModel
+import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeUserActionsViewModel
import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.Scene
@@ -49,7 +49,7 @@ import kotlinx.coroutines.flow.Flow
class NotificationsShadeScene
@Inject
constructor(
- private val actionsViewModelFactory: NotificationsShadeSceneActionsViewModel.Factory,
+ private val actionsViewModelFactory: NotificationsShadeUserActionsViewModel.Factory,
private val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
private val tintedIconManagerFactory: TintedIconManager.Factory,
@@ -61,12 +61,11 @@ constructor(
override val key = Scenes.NotificationsShade
- private val actionsViewModel: NotificationsShadeSceneActionsViewModel by lazy {
+ private val actionsViewModel: NotificationsShadeUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index 373383f0a2fe..d34295ea1d22 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -93,8 +93,8 @@ import com.android.systemui.notifications.ui.composable.NotificationStackCutoffG
import com.android.systemui.qs.footer.ui.compose.FooterActionsWithAnimatedVisibility
import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaLandscapeTopOffset
import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaOffset.InQS
-import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneActionsViewModel
import com.android.systemui.qs.ui.viewmodel.QuickSettingsSceneContentViewModel
+import com.android.systemui.qs.ui.viewmodel.QuickSettingsUserActionsViewModel
import com.android.systemui.res.R
import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.shared.model.Scenes
@@ -125,7 +125,7 @@ constructor(
private val shadeSession: SaveableSession,
private val notificationStackScrollView: Lazy<NotificationScrollView>,
private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
- private val actionsViewModelFactory: QuickSettingsSceneActionsViewModel.Factory,
+ private val actionsViewModelFactory: QuickSettingsUserActionsViewModel.Factory,
private val contentViewModelFactory: QuickSettingsSceneContentViewModel.Factory,
private val tintedIconManagerFactory: TintedIconManager.Factory,
private val batteryMeterViewControllerFactory: BatteryMeterViewController.Factory,
@@ -135,12 +135,11 @@ constructor(
) : ExclusiveActivatable(), Scene {
override val key = Scenes.QuickSettings
- private val actionsViewModel: QuickSettingsSceneActionsViewModel by lazy {
+ private val actionsViewModel: QuickSettingsUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
index 988c712b7980..f8d0588c9ae6 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeOverlay.kt
@@ -34,6 +34,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.scene.ContentScope
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.brightness.ui.compose.BrightnessSliderContainer
import com.android.systemui.compose.modifiers.sysuiResTag
@@ -51,6 +53,7 @@ import com.android.systemui.shade.ui.composable.OverlayShade
import com.android.systemui.statusbar.phone.ui.StatusBarIconController
import com.android.systemui.statusbar.phone.ui.TintedIconManager
import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
@SysUISingleton
class QuickSettingsShadeOverlay
@@ -69,6 +72,8 @@ constructor(
actionsViewModelFactory.create()
}
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
+
override suspend fun activate(): Nothing {
actionsViewModel.activate()
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt
index 9316eb90a7a2..e27c7e29ba50 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsShadeScene.kt
@@ -27,8 +27,8 @@ import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.rememberViewModel
-import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeSceneActionsViewModel
import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeSceneContentViewModel
+import com.android.systemui.qs.ui.viewmodel.QuickSettingsShadeUserActionsViewModel
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.Scene
import com.android.systemui.shade.ui.composable.ExpandedShadeHeader
@@ -43,7 +43,7 @@ import kotlinx.coroutines.flow.Flow
class QuickSettingsShadeScene
@Inject
constructor(
- private val actionsViewModelFactory: QuickSettingsShadeSceneActionsViewModel.Factory,
+ private val actionsViewModelFactory: QuickSettingsShadeUserActionsViewModel.Factory,
private val contentViewModelFactory: QuickSettingsShadeSceneContentViewModel.Factory,
private val shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
private val tintedIconManagerFactory: TintedIconManager.Factory,
@@ -53,12 +53,11 @@ constructor(
override val key = Scenes.QuickSettingsShade
- private val actionsViewModel: QuickSettingsShadeSceneActionsViewModel by lazy {
+ private val actionsViewModel: QuickSettingsShadeUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ActionableContent.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ActionableContent.kt
new file mode 100644
index 000000000000..8fe6893cb352
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/ActionableContent.kt
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.scene.ui.composable
+
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
+import kotlinx.coroutines.flow.Flow
+
+/** Defines interface for content that can respond to user-actions. */
+interface ActionableContent {
+ /**
+ * The mapping between [UserAction] and destination [UserActionResult]s.
+ *
+ * When the scene framework detects a user action, if the current scene has a map entry for that
+ * user action, the framework starts a transition to the content specified in the map.
+ *
+ * Once the content is shown, the scene framework will read this property and set up a collector
+ * to watch for new mapping values. For each map entry, the scene framework will set up user
+ * input handling for its [UserAction] and, if such a user action is detected, initiate a
+ * transition to the specified [UserActionResult].
+ *
+ * Note that reading from this method does _not_ mean that any user action has occurred.
+ * Instead, the property is read before any user action/gesture is detected so that the
+ * framework can decide whether to set up gesture/input detectors/listeners in case user actions
+ * of the given types ever occur.
+ *
+ * A missing value for a specific [UserAction] means that the user action of the given type is
+ * not currently active in the top-most content (in z-index order) and should be ignored by the
+ * framework until the top-most content changes.
+ */
+ val userActions: Flow<Map<UserAction, UserActionResult>>
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
index 6fb4724426fc..ae5dd8abb82e 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/GoneScene.kt
@@ -33,7 +33,7 @@ import com.android.systemui.qs.ui.composable.QuickSettings
import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaLandscapeTopOffset
import com.android.systemui.qs.ui.composable.QuickSettings.SharedValues.MediaOffset.Default
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.ui.viewmodel.GoneSceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.GoneUserActionsViewModel
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
import dagger.Lazy
@@ -50,14 +50,13 @@ class GoneScene
constructor(
private val notificationStackScrolLView: Lazy<NotificationScrollView>,
private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
- private val viewModelFactory: GoneSceneActionsViewModel.Factory,
+ private val viewModelFactory: GoneUserActionsViewModel.Factory,
) : ExclusiveActivatable(), Scene {
override val key = Scenes.Gone
- private val actionsViewModel: GoneSceneActionsViewModel by lazy { viewModelFactory.create() }
+ private val actionsViewModel: GoneUserActionsViewModel by lazy { viewModelFactory.create() }
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
override suspend fun onActivated(): Nothing {
actionsViewModel.activate()
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt
index d62befd10745..609ce90fd684 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Overlay.kt
@@ -18,9 +18,14 @@ package com.android.systemui.scene.ui.composable
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
+import com.android.compose.animation.scene.Back
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.OverlayKey
+import com.android.compose.animation.scene.UserAction
+import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.lifecycle.Activatable
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flowOf
/**
* Defines interface for classes that can describe an "overlay".
@@ -29,9 +34,17 @@ import com.android.systemui.lifecycle.Activatable
* container takes care of rendering any current overlays and allowing overlays to be shown, hidden,
* or replaced based on a user action.
*/
-interface Overlay : Activatable {
+interface Overlay : Activatable, ActionableContent {
/** Uniquely-identifying key for this overlay. The key must be unique within its container. */
val key: OverlayKey
+ /**
+ * The user actions supported by this overlay.
+ *
+ * @see [ActionableContent.userActions]
+ */
+ override val userActions: Flow<Map<UserAction, UserActionResult>>
+ get() = flowOf(mapOf(Back to UserActionResult.HideOverlay(key)))
+
@Composable fun ContentScope.Content(modifier: Modifier)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt
index 5319ec345d00..8d8ab8ee7949 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt
@@ -20,10 +20,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneScope
-import com.android.compose.animation.scene.UserAction
-import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.lifecycle.Activatable
-import kotlinx.coroutines.flow.Flow
/**
* Defines interface for classes that can describe a "scene".
@@ -33,32 +30,10 @@ import kotlinx.coroutines.flow.Flow
* based on either user action (for example, swiping down while on the lock screen scene may switch
* to the shade scene).
*/
-interface Scene : Activatable {
+interface Scene : Activatable, ActionableContent {
/** Uniquely-identifying key for this scene. The key must be unique within its container. */
val key: SceneKey
- /**
- * The mapping between [UserAction] and destination [UserActionResult]s.
- *
- * When the scene framework detects a user action, if the current scene has a map entry for that
- * user action, the framework starts a transition to the scene in the map.
- *
- * Once the [Scene] becomes the current one, the scene framework will read this property and set
- * up a collector to watch for new mapping values. If every map entry provided by the scene, the
- * framework will set up user input handling for its [UserAction] and, if such a user action is
- * detected, initiate a transition to the specified [UserActionResult].
- *
- * Note that reading from this method does _not_ mean that any user action has occurred.
- * Instead, the property is read before any user action/gesture is detected so that the
- * framework can decide whether to set up gesture/input detectors/listeners in case user actions
- * of the given types ever occur.
- *
- * Note that a missing value for a specific [UserAction] means that the user action of the given
- * type is not currently active in the scene and should be ignored by the framework, while the
- * current scene is this one.
- */
- val destinationScenes: Flow<Map<UserAction, UserActionResult>>
-
@Composable fun SceneScope.Content(modifier: Modifier)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
index 851fa3ff005e..a7e41ce05f58 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainer.kt
@@ -104,7 +104,7 @@ fun SceneContainer(
// TODO(b/359173565): Add overlay user actions when the API is final.
LaunchedEffect(currentSceneKey) {
try {
- sceneByKey[currentSceneKey]?.destinationScenes?.collectLatest { userActions ->
+ sceneByKey[currentSceneKey]?.userActions?.collectLatest { userActions ->
userActionsByContentKey[currentSceneKey] =
viewModel.resolveSceneFamilies(userActions)
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 5fcf5226a585..a03bf43c4c8f 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -108,8 +108,8 @@ import com.android.systemui.scene.session.ui.composable.SaveableSession
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.ui.composable.Scene
import com.android.systemui.shade.shared.model.ShadeMode
-import com.android.systemui.shade.ui.viewmodel.ShadeSceneActionsViewModel
import com.android.systemui.shade.ui.viewmodel.ShadeSceneContentViewModel
+import com.android.systemui.shade.ui.viewmodel.ShadeUserActionsViewModel
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
import com.android.systemui.statusbar.phone.StatusBarLocation
@@ -154,7 +154,7 @@ class ShadeScene
constructor(
private val shadeSession: SaveableSession,
private val notificationStackScrollView: Lazy<NotificationScrollView>,
- private val actionsViewModelFactory: ShadeSceneActionsViewModel.Factory,
+ private val actionsViewModelFactory: ShadeUserActionsViewModel.Factory,
private val contentViewModelFactory: ShadeSceneContentViewModel.Factory,
private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
private val tintedIconManagerFactory: TintedIconManager.Factory,
@@ -167,7 +167,7 @@ constructor(
override val key = Scenes.Shade
- private val actionsViewModel: ShadeSceneActionsViewModel by lazy {
+ private val actionsViewModel: ShadeUserActionsViewModel by lazy {
actionsViewModelFactory.create()
}
@@ -175,8 +175,7 @@ constructor(
actionsViewModel.activate()
}
- override val destinationScenes: Flow<Map<UserAction, UserActionResult>> =
- actionsViewModel.actions
+ override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions
@Composable
override fun SceneScope.Content(
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
index 4aa50b586c1b..b30f2b7002ce 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/AnimateSharedAsState.kt
@@ -399,26 +399,53 @@ private class AnimatedStateImpl<T, Delta>(
val fromValue = sharedValue[transition.fromContent]
val toValue = sharedValue[transition.toContent]
- return if (fromValue != null && toValue != null) {
- if (fromValue == toValue) {
- // Optimization: avoid reading progress if the values are the same, so we don't
- // relayout/redraw for nothing.
- fromValue
- } else {
- val overscrollSpec = transition.currentOverscrollSpec
- val progress =
- when {
- overscrollSpec == null -> {
- if (canOverflow) transition.progress
- else transition.progress.fastCoerceIn(0f, 1f)
- }
- overscrollSpec.content == transition.toContent -> 1f
- else -> 0f
- }
-
- sharedValue.type.lerp(fromValue, toValue, progress)
+ if (fromValue == null && toValue == null) {
+ return null
+ }
+
+ if (fromValue != null && toValue != null) {
+ return interpolateSharedValue(fromValue, toValue, transition, sharedValue)
+ }
+
+ if (transition is TransitionState.Transition.ReplaceOverlay) {
+ val currentSceneValue = sharedValue[transition.currentScene]
+ if (currentSceneValue != null) {
+ return interpolateSharedValue(
+ fromValue = fromValue ?: currentSceneValue,
+ toValue = toValue ?: currentSceneValue,
+ transition,
+ sharedValue,
+ )
+ }
+ }
+
+ return fromValue ?: toValue
+ }
+
+ private fun interpolateSharedValue(
+ fromValue: T,
+ toValue: T,
+ transition: TransitionState.Transition,
+ sharedValue: SharedValue<T, *>,
+ ): T? {
+ if (fromValue == toValue) {
+ // Optimization: avoid reading progress if the values are the same, so we don't
+ // relayout/redraw for nothing.
+ return fromValue
+ }
+
+ val overscrollSpec = transition.currentOverscrollSpec
+ val progress =
+ when {
+ overscrollSpec == null -> {
+ if (canOverflow) transition.progress
+ else transition.progress.fastCoerceIn(0f, 1f)
+ }
+ overscrollSpec.content == transition.toContent -> 1f
+ else -> 0f
}
- } else fromValue ?: toValue
+
+ return sharedValue.type.lerp(fromValue, toValue, progress)
}
private fun transition(sharedValue: SharedValue<T, Delta>): TransitionState.Transition? {
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
index 9b1740dc700a..56c08b9d4789 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/Element.kt
@@ -313,10 +313,27 @@ internal class ElementNode(
// If this element is not supposed to be laid out now, either because it is not part of any
// ongoing transition or the other content of its transition is overscrolling, then lay out
// the element normally and don't place it.
- val overscrollScene = transition?.currentOverscrollSpec?.content
- val isOtherSceneOverscrolling = overscrollScene != null && overscrollScene != content.key
- if (isOtherSceneOverscrolling) {
- return doNotPlace(measurable, constraints)
+ val overscrollContent = transition?.currentOverscrollSpec?.content
+ if (overscrollContent != null && overscrollContent != content.key) {
+ when (transition) {
+ is TransitionState.Transition.ChangeScene ->
+ return doNotPlace(measurable, constraints)
+
+ // If we are overscrolling an overlay that does not contain an element that is in
+ // the current scene, place it in that scene otherwise the element won't be placed
+ // at all.
+ is TransitionState.Transition.ShowOrHideOverlay,
+ is TransitionState.Transition.ReplaceOverlay -> {
+ if (
+ content.key == transition.currentScene &&
+ overscrollContent !in element.stateByContent
+ ) {
+ return placeNormally(measurable, constraints)
+ } else {
+ return doNotPlace(measurable, constraints)
+ }
+ }
+ }
}
val placeable =
@@ -836,19 +853,32 @@ private fun shouldPlaceElement(
content,
element.key,
transition,
+ isInContent = { it in element.stateByContent },
)
}
-internal fun shouldPlaceOrComposeSharedElement(
+internal inline fun shouldPlaceOrComposeSharedElement(
layoutImpl: SceneTransitionLayoutImpl,
content: ContentKey,
element: ElementKey,
transition: TransitionState.Transition,
+ isInContent: (ContentKey) -> Boolean,
): Boolean {
- // If we are overscrolling, only place/compose the element in the overscrolling scene.
- val overscrollScene = transition.currentOverscrollSpec?.content
- if (overscrollScene != null) {
- return content == overscrollScene
+ val overscrollContent = transition.currentOverscrollSpec?.content
+ if (overscrollContent != null) {
+ return when (transition) {
+ // If we are overscrolling between scenes, only place/compose the element in the
+ // overscrolling scene.
+ is TransitionState.Transition.ChangeScene -> content == overscrollContent
+
+ // If we are overscrolling an overlay, place/compose the element if [content] is the
+ // overscrolling content or if [content] is the current scene and the overscrolling
+ // overlay does not contain the element.
+ is TransitionState.Transition.ReplaceOverlay,
+ is TransitionState.Transition.ShowOrHideOverlay ->
+ content == overscrollContent ||
+ (content == transition.currentScene && !isInContent(overscrollContent))
+ }
}
val scenePicker = element.contentPicker
@@ -1230,17 +1260,30 @@ private inline fun <T> computeValue(
// elements follow the finger direction.
val isSharedElement = fromState != null && toState != null
if (isSharedElement && isSharedElementEnabled(element.key, transition)) {
- val start = contentValue(fromState!!)
- val end = contentValue(toState!!)
-
- // TODO(b/316901148): Remove checks to isSpecified() once the lookahead pass runs for all
- // nodes before the intermediate layout pass.
- if (!isSpecified(start)) return end
- if (!isSpecified(end)) return start
+ return interpolateSharedElement(
+ transition = transition,
+ contentValue = contentValue,
+ fromState = fromState!!,
+ toState = toState!!,
+ isSpecified = isSpecified,
+ lerp = lerp,
+ )
+ }
- // Make sure we don't read progress if values are the same and we don't need to interpolate,
- // so we don't invalidate the phase where this is read.
- return if (start == end) start else lerp(start, end, transition.progress)
+ // If we are replacing an overlay and the element is both in a single overlay and in the current
+ // scene, interpolate the state of the element using the current scene as the other scene.
+ if (!isSharedElement && transition is TransitionState.Transition.ReplaceOverlay) {
+ val currentSceneState = element.stateByContent[transition.currentScene]
+ if (currentSceneState != null) {
+ return interpolateSharedElement(
+ transition = transition,
+ contentValue = contentValue,
+ fromState = fromState ?: currentSceneState,
+ toState = toState ?: currentSceneState,
+ isSpecified = isSpecified,
+ lerp = lerp,
+ )
+ }
}
// Get the transformed value, i.e. the target value at the beginning (for entering elements) or
@@ -1383,3 +1426,24 @@ private inline fun <T> computeValue(
lerp(idleValue, targetValue, rangeProgress)
}
}
+
+private inline fun <T> interpolateSharedElement(
+ transition: TransitionState.Transition,
+ contentValue: (Element.State) -> T,
+ fromState: Element.State,
+ toState: Element.State,
+ isSpecified: (T) -> Boolean,
+ lerp: (T, T, Float) -> T
+): T {
+ val start = contentValue(fromState)
+ val end = contentValue(toState)
+
+ // TODO(b/316901148): Remove checks to isSpecified() once the lookahead pass runs for all
+ // nodes before the intermediate layout pass.
+ if (!isSpecified(start)) return end
+ if (!isSpecified(end)) return start
+
+ // Make sure we don't read progress if values are the same and we don't need to interpolate,
+ // so we don't invalidate the phase where this is read.
+ return if (start == end) start else lerp(start, end, transition.progress)
+}
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
index 715222cfd9da..471ad3fee9fb 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/MovableElement.kt
@@ -194,11 +194,13 @@ private fun shouldComposeMovableElement(
is TransitionState.Transition -> {
// During transitions, always compose movable elements in the scene picked by their
// content picker.
+ val contents = element.contentPicker.contents
shouldPlaceOrComposeSharedElement(
layoutImpl,
content,
element,
elementState,
+ isInContent = { contents.contains(it) }
)
}
}
@@ -208,8 +210,8 @@ private fun movableElementState(
element: MovableElementKey,
transitionStates: List<TransitionState>,
): TransitionState? {
- val content = element.contentPicker.contents
- return elementState(transitionStates, isInContent = { content.contains(it) })
+ val contents = element.contentPicker.contents
+ return elementState(transitionStates, isInContent = { contents.contains(it) })
}
private fun movableElementContentWhenIdle(
diff --git a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
index 094f20e337d6..061613f999c6 100644
--- a/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
+++ b/packages/SystemUI/compose/scene/src/com/android/compose/animation/scene/SceneTransitionLayout.kt
@@ -550,6 +550,22 @@ sealed class UserActionResult(
*/
requiresFullDistanceSwipe: Boolean = false,
): UserActionResult = ChangeScene(toScene, transitionKey, requiresFullDistanceSwipe)
+
+ /** A [UserActionResult] that shows [toOverlay]. */
+ operator fun invoke(
+ /** The overlay we should be transitioning to during the [UserAction]. */
+ toOverlay: OverlayKey,
+
+ /** The key of the transition that should be used. */
+ transitionKey: TransitionKey? = null,
+
+ /**
+ * If `true`, the swipe will be committed if only if the user swiped at least the swipe
+ * distance, i.e. the transition progress was already equal to or bigger than 100% when
+ * the user released their finger.
+ */
+ requiresFullDistanceSwipe: Boolean = false,
+ ): UserActionResult = ShowOverlay(toOverlay, transitionKey, requiresFullDistanceSwipe)
}
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
index bec2bb2baa3c..471362ba19e9 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/OverlayTest.kt
@@ -18,14 +18,17 @@ package com.android.compose.animation.scene
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
+import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
+import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
@@ -42,7 +45,12 @@ import com.android.compose.animation.scene.TestOverlays.OverlayA
import com.android.compose.animation.scene.TestOverlays.OverlayB
import com.android.compose.animation.scene.TestScenes.SceneA
import com.android.compose.test.assertSizeIsEqualTo
+import com.android.compose.test.setContentAndCreateMainScope
+import com.android.compose.test.subjects.assertThat
+import com.android.compose.test.transition
+import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -524,4 +532,162 @@ class OverlayTest {
}
}
}
+
+ @Test
+ fun replaceAnimation_elementInCurrentSceneAndOneOverlay() {
+ val sharedIntKey = ValueKey("sharedInt")
+ val sharedIntValueByContent = mutableMapOf<ContentKey, Int>()
+
+ @Composable
+ fun SceneScope.animateContentInt(targetValue: Int) {
+ val animatedValue = animateContentIntAsState(targetValue, sharedIntKey)
+ LaunchedEffect(animatedValue) {
+ try {
+ snapshotFlow { animatedValue.value }
+ .collect { sharedIntValueByContent[contentKey] = it }
+ } finally {
+ sharedIntValueByContent.remove(contentKey)
+ }
+ }
+ }
+
+ rule.testReplaceOverlayTransition(
+ currentSceneContent = {
+ Box(Modifier.size(width = 180.dp, height = 120.dp)) {
+ animateContentInt(targetValue = 1_000)
+ Foo(width = 60.dp, height = 40.dp)
+ }
+ },
+ fromContent = {},
+ fromAlignment = Alignment.TopStart,
+ toContent = {
+ animateContentInt(targetValue = 2_000)
+ Foo(width = 100.dp, height = 80.dp)
+ },
+ transition = {
+ // 4 frames of animation
+ spec = tween(4 * 16, easing = LinearEasing)
+ },
+ ) {
+ // Foo moves from (0,0) with a size of 60x40dp to centered (in a 180x120dp Box) with a
+ // size of 100x80dp, so at (40,20).
+ //
+ // The animated Int goes from 1_000 to 2_000.
+ before {
+ rule
+ .onNode(isElement(TestElements.Foo, content = SceneA))
+ .assertSizeIsEqualTo(60.dp, 40.dp)
+ .assertPositionInRootIsEqualTo(0.dp, 0.dp)
+ rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+ rule.onNode(isElement(TestElements.Foo, content = OverlayB)).assertDoesNotExist()
+
+ assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_000)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayB)
+ }
+
+ at(16) {
+ rule
+ .onNode(isElement(TestElements.Foo, content = SceneA))
+ .assertExists()
+ .assertIsNotDisplayed()
+ rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+ rule
+ .onNode(isElement(TestElements.Foo, content = OverlayB))
+ .assertSizeIsEqualTo(70.dp, 50.dp)
+ .assertPositionInRootIsEqualTo(10.dp, 5.dp)
+
+ assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_250)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+ assertThat(sharedIntValueByContent).containsEntry(OverlayB, 1_250)
+ }
+
+ at(32) {
+ rule
+ .onNode(isElement(TestElements.Foo, content = SceneA))
+ .assertExists()
+ .assertIsNotDisplayed()
+ rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+ rule
+ .onNode(isElement(TestElements.Foo, content = OverlayB))
+ .assertSizeIsEqualTo(80.dp, 60.dp)
+ .assertPositionInRootIsEqualTo(20.dp, 10.dp)
+
+ assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_500)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+ assertThat(sharedIntValueByContent).containsEntry(OverlayB, 1_500)
+ }
+
+ at(48) {
+ rule
+ .onNode(isElement(TestElements.Foo, content = SceneA))
+ .assertExists()
+ .assertIsNotDisplayed()
+ rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+ rule
+ .onNode(isElement(TestElements.Foo, content = OverlayB))
+ .assertSizeIsEqualTo(90.dp, 70.dp)
+ .assertPositionInRootIsEqualTo(30.dp, 15.dp)
+
+ assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_750)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+ assertThat(sharedIntValueByContent).containsEntry(OverlayB, 1_750)
+ }
+
+ after {
+ rule
+ .onNode(isElement(TestElements.Foo, content = SceneA))
+ .assertExists()
+ .assertIsNotDisplayed()
+ rule.onNode(isElement(TestElements.Foo, content = OverlayA)).assertDoesNotExist()
+ rule
+ .onNode(isElement(TestElements.Foo, content = OverlayB))
+ .assertSizeIsEqualTo(100.dp, 80.dp)
+ .assertPositionInRootIsEqualTo(40.dp, 20.dp)
+
+ // Outside of transitions, the value is equal to the target value in each content.
+ assertThat(sharedIntValueByContent).containsEntry(SceneA, 1_000)
+ assertThat(sharedIntValueByContent).doesNotContainKey(OverlayA)
+ assertThat(sharedIntValueByContent).containsEntry(OverlayB, 2_000)
+ }
+ }
+ }
+
+ @Test
+ fun overscrollingOverlay_movableElementNotInOverlay() {
+ val state =
+ rule.runOnUiThread {
+ MutableSceneTransitionLayoutStateImpl(
+ SceneA,
+ transitions {
+ // Make OverlayA overscrollable.
+ overscroll(OverlayA, orientation = Orientation.Horizontal) {
+ translate(ElementKey("elementThatDoesNotExist"), x = 10.dp)
+ }
+ }
+ )
+ }
+
+ val key = MovableElementKey("Foo", contents = setOf(SceneA))
+ val movableElementChildTag = "movableElementChildTag"
+ val scope =
+ rule.setContentAndCreateMainScope {
+ SceneTransitionLayout(state) {
+ scene(SceneA) {
+ MovableElement(key, Modifier) {
+ content { Box(Modifier.testTag(movableElementChildTag).size(100.dp)) }
+ }
+ }
+ overlay(OverlayA) { /* Does not contain the element. */ }
+ }
+ }
+
+ // Overscroll on Overlay A.
+ scope.launch { state.startTransition(transition(SceneA, OverlayA, progress = { 1.5f })) }
+ rule
+ .onNode(hasTestTag(movableElementChildTag) and inContent(SceneA))
+ .assertPositionInRootIsEqualTo(0.dp, 0.dp)
+ .assertSizeIsEqualTo(100.dp)
+ .assertIsDisplayed()
+ }
}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
index cd20a29a05d9..d356c25262e8 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/animation/scene/SceneTransitionLayoutStateTest.kt
@@ -32,7 +32,7 @@ import com.android.compose.animation.scene.subjects.assertThat
import com.android.compose.animation.scene.transition.link.StateLink
import com.android.compose.animation.scene.transition.seekToScene
import com.android.compose.test.MonotonicClockTestScope
-import com.android.compose.test.TestTransition
+import com.android.compose.test.TestSceneTransition
import com.android.compose.test.runMonotonicClockTest
import com.android.compose.test.transition
import com.google.common.truth.Truth.assertThat
@@ -556,8 +556,8 @@ class SceneTransitionLayoutStateTest {
@Test
fun multipleTransitions() = runTest {
- val frozenTransitions = mutableSetOf<TestTransition>()
- fun onFreezeAndAnimate(transition: TestTransition): () -> Unit {
+ val frozenTransitions = mutableSetOf<TestSceneTransition>()
+ fun onFreezeAndAnimate(transition: TestSceneTransition): () -> Unit {
// Instead of letting the transition finish when it is frozen, we put the transition in
// the frozenTransitions set so that we can verify that freezeAndAnimateToCurrentState()
// is called when expected and then we call finish() ourselves to finish the
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt
new file mode 100644
index 000000000000..646cff8b944c
--- /dev/null
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestOverlayTransition.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.compose.test
+
+import androidx.compose.foundation.gestures.Orientation
+import com.android.compose.animation.scene.ContentKey
+import com.android.compose.animation.scene.OverlayKey
+import com.android.compose.animation.scene.SceneKey
+import com.android.compose.animation.scene.SceneTransitionLayoutImpl
+import com.android.compose.animation.scene.content.state.TransitionState
+import com.android.compose.animation.scene.content.state.TransitionState.Transition
+import kotlinx.coroutines.CompletableDeferred
+
+/** A [Transition.ShowOrHideOverlay] for tests that will be finished once [finish] is called. */
+abstract class TestOverlayTransition(
+ fromScene: SceneKey,
+ overlay: OverlayKey,
+ replacedTransition: Transition?,
+) :
+ Transition.ShowOrHideOverlay(
+ overlay = overlay,
+ fromOrToScene = fromScene,
+ fromContent = fromScene,
+ toContent = overlay,
+ replacedTransition = replacedTransition,
+ ) {
+ private val finishCompletable = CompletableDeferred<Unit>()
+
+ override suspend fun run() {
+ finishCompletable.await()
+ }
+
+ /** Finish this transition. */
+ fun finish() {
+ finishCompletable.complete(Unit)
+ }
+}
+
+/** A utility to easily create a [TestOverlayTransition] in tests. */
+fun transition(
+ fromScene: SceneKey,
+ overlay: OverlayKey,
+ isEffectivelyShown: () -> Boolean = { true },
+ progress: () -> Float = { 0f },
+ progressVelocity: () -> Float = { 0f },
+ previewProgress: () -> Float = { 0f },
+ previewProgressVelocity: () -> Float = { 0f },
+ isInPreviewStage: () -> Boolean = { false },
+ interruptionProgress: () -> Float = { 0f },
+ isInitiatedByUserInput: Boolean = false,
+ isUserInputOngoing: Boolean = false,
+ isUpOrLeft: Boolean = false,
+ bouncingContent: ContentKey? = null,
+ orientation: Orientation = Orientation.Horizontal,
+ onFreezeAndAnimate: ((TestOverlayTransition) -> Unit)? = null,
+ replacedTransition: Transition? = null,
+): TestOverlayTransition {
+ return object :
+ TestOverlayTransition(fromScene, overlay, replacedTransition),
+ TransitionState.HasOverscrollProperties {
+ override val isEffectivelyShown: Boolean
+ get() = isEffectivelyShown()
+
+ override val progress: Float
+ get() = progress()
+
+ override val progressVelocity: Float
+ get() = progressVelocity()
+
+ override val previewProgress: Float
+ get() = previewProgress()
+
+ override val previewProgressVelocity: Float
+ get() = previewProgressVelocity()
+
+ override val isInPreviewStage: Boolean
+ get() = isInPreviewStage()
+
+ override val isInitiatedByUserInput: Boolean = isInitiatedByUserInput
+ override val isUserInputOngoing: Boolean = isUserInputOngoing
+ override val isUpOrLeft: Boolean = isUpOrLeft
+ override val bouncingContent: ContentKey? = bouncingContent
+ override val orientation: Orientation = orientation
+ override val absoluteDistance = 0f
+
+ override fun freezeAndAnimateToCurrentState() {
+ if (onFreezeAndAnimate != null) {
+ onFreezeAndAnimate(this)
+ } else {
+ finish()
+ }
+ }
+
+ override fun interruptionProgress(layoutImpl: SceneTransitionLayoutImpl): Float {
+ return interruptionProgress()
+ }
+ }
+}
diff --git a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt
index a6a83eedb2ac..d24b895c3050 100644
--- a/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestTransition.kt
+++ b/packages/SystemUI/compose/scene/tests/src/com/android/compose/test/TestSceneTransition.kt
@@ -24,8 +24,8 @@ import com.android.compose.animation.scene.content.state.TransitionState
import com.android.compose.animation.scene.content.state.TransitionState.Transition
import kotlinx.coroutines.CompletableDeferred
-/** A transition for tests that will be finished once [finish] is called. */
-abstract class TestTransition(
+/** A [Transition.ChangeScene] for tests that will be finished once [finish] is called. */
+abstract class TestSceneTransition(
fromScene: SceneKey,
toScene: SceneKey,
replacedTransition: Transition?,
@@ -42,7 +42,7 @@ abstract class TestTransition(
}
}
-/** A utility to easily create a [TestTransition] in tests. */
+/** A utility to easily create a [TestSceneTransition] in tests. */
fun transition(
from: SceneKey,
to: SceneKey,
@@ -58,11 +58,11 @@ fun transition(
isUpOrLeft: Boolean = false,
bouncingContent: ContentKey? = null,
orientation: Orientation = Orientation.Horizontal,
- onFreezeAndAnimate: ((TestTransition) -> Unit)? = null,
+ onFreezeAndAnimate: ((TestSceneTransition) -> Unit)? = null,
replacedTransition: Transition? = null,
-): TestTransition {
+): TestSceneTransition {
return object :
- TestTransition(from, to, replacedTransition), TransitionState.HasOverscrollProperties {
+ TestSceneTransition(from, to, replacedTransition), TransitionState.HasOverscrollProperties {
override val currentScene: SceneKey
get() = current()
diff --git a/packages/SystemUI/docs/scene.md b/packages/SystemUI/docs/scene.md
index a7740c677d51..0ac15c583b29 100644
--- a/packages/SystemUI/docs/scene.md
+++ b/packages/SystemUI/docs/scene.md
@@ -124,8 +124,8 @@ Each scene is defined as an implementation of the
[`Scene`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/Scene.kt)
interface, which has three parts: 1. The `key` property returns the
[`SceneKey`](https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/packages/SystemUI/src/com/android/systemui/scene/shared/model/SceneKey.kt)
-that uniquely identifies that scene 2. The `destinationScenes` `Flow` returns
-the (potentially ever-changing) set of navigation edges to other scenes, based
+that uniquely identifies that scene 2. The `userActions` `Flow` returns
+the (potentially ever-changing) set of navigation edges to other content, based
on user-actions, which is how the navigation graph is defined (see
[the Scene navigation](#Scene-navigation) section for more) 3. The `Content`
function which uses
@@ -141,7 +141,7 @@ For example:
@SysUISingleton class YourScene @Inject constructor( /* your dependencies here */ ) : Scene {
override val key = SceneKey.YourScene
- override val destinationScenes: StateFlow<Map<UserAction, SceneModel>> =
+ override val userActions: StateFlow<Map<UserAction, SceneModel>> =
MutableStateFlow<Map<UserAction, SceneModel>>(
mapOf(
// This is where scene navigation is defined, more on that below.
diff --git a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index 18ed22a3f4a2..e444db4895d4 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -18,10 +18,8 @@
package com.android.keyguard
import android.app.admin.DevicePolicyManager
-import android.app.admin.flags.Flags as DevicePolicyFlags
import android.content.res.Configuration
import android.media.AudioManager
-import android.platform.test.annotations.EnableFlags
import android.telephony.TelephonyManager
import android.testing.TestableLooper.RunWithLooper
import android.testing.TestableResources
@@ -942,7 +940,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DevicePolicyFlags.FLAG_HEADLESS_SINGLE_USER_FIXES)
fun showAlmostAtWipeDialog_calledOnMainUser_setsCorrectUserType() {
val mainUserId = 10
@@ -959,7 +956,6 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DevicePolicyFlags.FLAG_HEADLESS_SINGLE_USER_FIXES)
fun showAlmostAtWipeDialog_calledOnNonMainUser_setsCorrectUserType() {
val secondaryUserId = 10
val mainUserId = 0
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
index 0c5e726e17aa..080b48af2af1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
@@ -17,8 +17,6 @@
package com.android.systemui.authentication.domain.interactor
import android.app.admin.DevicePolicyManager
-import android.app.admin.flags.Flags as DevicePolicyFlags
-import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.widget.LockPatternUtils
@@ -414,7 +412,6 @@ class AuthenticationInteractorTest : SysuiTestCase() {
}
@Test
- @EnableFlags(DevicePolicyFlags.FLAG_HEADLESS_SINGLE_USER_FIXES)
fun upcomingWipe() =
testScope.runTest {
val upcomingWipe by collectLastValue(underTest.upcomingWipe)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModelTest.kt
index a86a0c022c21..f58bbc3cf0cf 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModelTest.kt
@@ -44,17 +44,17 @@ import org.junit.runner.RunWith
@SmallTest
@RunWith(AndroidJUnit4::class)
@EnableSceneContainer
-class BouncerSceneActionsViewModelTest : SysuiTestCase() {
+class BouncerUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private lateinit var underTest: BouncerSceneActionsViewModel
+ private lateinit var underTest: BouncerUserActionsViewModel
@Before
fun setUp() {
kosmos.sceneContainerStartable.start()
- underTest = kosmos.bouncerSceneActionsViewModel
+ underTest = kosmos.bouncerUserActionsViewModel
underTest.activateIn(testScope)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
index ec8cc4d493d0..53d82d7b2a07 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
@@ -34,8 +34,6 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.testing.FakeMetricsLogger;
import com.android.systemui.SysuiTestCase;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
@@ -83,7 +81,6 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
private final FalsingClassifier.Result mPassedResult = FalsingClassifier.Result.passed(1);
private final FalsingClassifier.Result mFalsedResult =
FalsingClassifier.Result.falsed(1, getClass().getSimpleName(), "");
- private final FakeFeatureFlags mFakeFeatureFlags = new FakeFeatureFlags();
@Before
public void setup() {
@@ -101,8 +98,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
mMetricsLogger, mClassifiers, mSingleTapClassifier, mLongTapClassifier,
mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
- mAccessibilityManager, false, mFakeFeatureFlags);
- mFakeFeatureFlags.set(Flags.FALSING_OFF_FOR_UNFOLDED, true);
+ mAccessibilityManager, false);
}
@Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
index 5e6ff73e5e5e..74265749f11c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/dreams/DreamOverlayServiceTest.kt
@@ -233,7 +233,7 @@ class DreamOverlayServiceTest : SysuiTestCase() {
.thenReturn(dreamOverlayComponent)
val ambientTouchComponent = mock<AmbientTouchComponent>()
- whenever(ambientTouchComponentFactory.create(any(), any()))
+ whenever(ambientTouchComponentFactory.create(any(), any(), any()))
.thenReturn(ambientTouchComponent)
whenever(ambientTouchComponent.getTouchMonitor()).thenReturn(mTouchMonitor)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
index ca15eff4610b..34d926a23edb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractorTest.kt
@@ -24,6 +24,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.contextualeducation.GestureType
+import com.android.systemui.contextualeducation.GestureType.ALL_APPS
import com.android.systemui.contextualeducation.GestureType.BACK
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.education.data.model.GestureEduModel
@@ -220,17 +221,19 @@ class KeyboardTouchpadEduInteractorTest : SysuiTestCase() {
verify(kosmos.mockEduInputManager)
.registerKeyGestureEventListener(any(), listenerCaptor.capture())
- val backGestureEvent =
+ val allAppsKeyGestureEvent =
KeyGestureEvent(
/* deviceId= */ 1,
- intArrayOf(KeyEvent.KEYCODE_ESCAPE),
+ IntArray(0),
KeyEvent.META_META_ON,
- KeyGestureEvent.KEY_GESTURE_TYPE_BACK
+ KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS
)
- listenerCaptor.value.onKeyGestureEvent(backGestureEvent)
+ listenerCaptor.value.onKeyGestureEvent(allAppsKeyGestureEvent)
val model by
- collectLastValue(kosmos.contextualEducationRepository.readGestureEduModelFlow(BACK))
+ collectLastValue(
+ kosmos.contextualEducationRepository.readGestureEduModelFlow(ALL_APPS)
+ )
assertThat(model?.lastShortcutTriggeredTime).isEqualTo(eduClock.instant())
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt
index 86b3f33b7555..0a0ded7ec861 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModelTest.kt
@@ -34,6 +34,7 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -85,26 +86,22 @@ class LockscreenToDozingTransitionViewModelTest : SysuiTestCase() {
testScope.runTest {
fingerprintPropertyRepository.supportsUdfps()
biometricSettingsRepository.setIsFingerprintAuthEnrolledAndEnabled(false)
+
val values by collectValues(underTest.deviceEntryParentViewAlpha)
+ runCurrent()
keyguardTransitionRepository.sendTransitionSteps(
- listOf(
- step(0f, TransitionState.STARTED),
- step(0f),
- step(0.1f),
- step(0.2f),
- step(0.3f),
- step(1f),
- ),
+ from = KeyguardState.LOCKSCREEN,
+ to = KeyguardState.DOZING,
testScope,
)
- values.forEach { assertThat(it).isEqualTo(0f) }
+ assertThat(values[0]).isEqualTo(1f)
+ assertThat(values[1]).isEqualTo(0f)
}
-
@Test
- fun lockscreenAlphaFadesOutAndFinishesVisible() =
+ fun lockscreenAlphaDoesNotFadeOut() =
testScope.runTest {
val alpha by collectValues(underTest.lockscreenAlpha)
keyguardTransitionRepository.sendTransitionSteps(
@@ -113,31 +110,7 @@ class LockscreenToDozingTransitionViewModelTest : SysuiTestCase() {
testScope,
)
- assertThat(alpha[0]).isEqualTo(1f)
- // Halfway through, it will have faded out
- assertThat(alpha[1]).isEqualTo(0f)
- // FINISHED alpha should be visible, to support pulsing
- assertThat(alpha[2]).isEqualTo(1f)
- }
-
- @Test
- fun deviceEntryBackgroundViewDisappear() =
- testScope.runTest {
- val values by collectValues(underTest.deviceEntryBackgroundViewAlpha)
-
- keyguardTransitionRepository.sendTransitionSteps(
- listOf(
- step(0f, TransitionState.STARTED),
- step(0f),
- step(0.1f),
- step(0.2f),
- step(0.3f),
- step(1f),
- ),
- testScope,
- )
-
- values.forEach { assertThat(it).isEqualTo(0f) }
+ alpha.forEach { assertThat(it).isEqualTo(1f) }
}
private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
index c66ebf3a31e0..4253c29d241c 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModelTest.kt
@@ -63,7 +63,7 @@ import platform.test.runner.parameterized.Parameters
@RunWith(ParameterizedAndroidJunit4::class)
@RunWithLooper
@EnableSceneContainer
-class LockscreenSceneActionsViewModelTest : SysuiTestCase() {
+class LockscreenUserActionsViewModelTest : SysuiTestCase() {
companion object {
private const val parameterCount = 6
@@ -170,7 +170,7 @@ class LockscreenSceneActionsViewModelTest : SysuiTestCase() {
@Test
@EnableFlags(Flags.FLAG_COMMUNAL_HUB)
- fun destinationScenes() =
+ fun userActions() =
testScope.runTest {
underTest.activateIn(this)
kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
@@ -193,9 +193,9 @@ class LockscreenSceneActionsViewModelTest : SysuiTestCase() {
},
)
- val destinationScenes by collectLastValue(underTest.actions)
+ val userActions by collectLastValue(underTest.actions)
val downDestination =
- destinationScenes?.get(
+ userActions?.get(
Swipe(
SwipeDirection.Down,
fromSource = Edge.Top.takeIf { downFromEdge },
@@ -227,11 +227,10 @@ class LockscreenSceneActionsViewModelTest : SysuiTestCase() {
val upScene by
collectLastValue(
- (destinationScenes?.get(Swipe(SwipeDirection.Up))
- as? UserActionResult.ChangeScene)
- ?.toScene
- ?.let { scene -> kosmos.sceneInteractor.resolveSceneFamily(scene) }
- ?: flowOf(null)
+ (userActions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene?.let {
+ scene ->
+ kosmos.sceneInteractor.resolveSceneFamily(scene)
+ } ?: flowOf(null)
)
assertThat(upScene)
@@ -244,11 +243,10 @@ class LockscreenSceneActionsViewModelTest : SysuiTestCase() {
val leftScene by
collectLastValue(
- (destinationScenes?.get(Swipe(SwipeDirection.Left))
- as? UserActionResult.ChangeScene)
- ?.toScene
- ?.let { scene -> kosmos.sceneInteractor.resolveSceneFamily(scene) }
- ?: flowOf(null)
+ (userActions?.get(Swipe.Left) as? UserActionResult.ChangeScene)?.toScene?.let {
+ scene ->
+ kosmos.sceneInteractor.resolveSceneFamily(scene)
+ } ?: flowOf(null)
)
assertThat(leftScene)
@@ -260,8 +258,8 @@ class LockscreenSceneActionsViewModelTest : SysuiTestCase() {
)
}
- private fun createLockscreenSceneViewModel(): LockscreenSceneActionsViewModel {
- return LockscreenSceneActionsViewModel(
+ private fun createLockscreenSceneViewModel(): LockscreenUserActionsViewModel {
+ return LockscreenUserActionsViewModel(
deviceEntryInteractor = kosmos.deviceEntryInteractor,
communalInteractor = kosmos.communalInteractor,
shadeInteractor = kosmos.shadeInteractor,
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
index 22e589637432..c1dcf37498d7 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataLoaderTest.kt
@@ -34,7 +34,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS
-import com.android.systemui.flags.Flags.MEDIA_SESSION_ACTIONS
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.graphics.imageLoader
import com.android.systemui.kosmos.testDispatcher
@@ -96,7 +95,6 @@ class MediaDataLoaderTest : SysuiTestCase() {
@Before
fun setUp() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
mediaControllerFactory.setControllerForToken(session.sessionToken, mediaController)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModelTest.kt
index ed7f96fb2b66..46b02e92a4f9 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModelTest.kt
@@ -37,7 +37,7 @@ import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.domain.resolver.homeSceneFamilyResolver
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.shade.ui.viewmodel.notificationsShadeSceneActionsViewModel
+import com.android.systemui.shade.ui.viewmodel.notificationsShadeUserActionsViewModel
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -52,14 +52,14 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
-class NotificationsShadeSceneActionsViewModelTest : SysuiTestCase() {
+class NotificationsShadeUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val sceneInteractor by lazy { kosmos.sceneInteractor }
private val deviceUnlockedInteractor by lazy { kosmos.deviceUnlockedInteractor }
- private val underTest by lazy { kosmos.notificationsShadeSceneActionsViewModel }
+ private val underTest by lazy { kosmos.notificationsShadeUserActionsViewModel }
@Test
fun upTransitionSceneKey_deviceLocked_lockscreen() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelTest.kt
index ba527d7ad2b8..32772d20a76a 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelTest.kt
@@ -53,14 +53,14 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
-class QuickSettingsShadeSceneActionsViewModelTest : SysuiTestCase() {
+class QuickSettingsShadeUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val sceneInteractor = kosmos.sceneInteractor
private val deviceUnlockedInteractor = kosmos.deviceUnlockedInteractor
- private val underTest by lazy { kosmos.quickSettingsShadeSceneActionsViewModel }
+ private val underTest by lazy { kosmos.quickSettingsShadeUserActionsViewModel }
@Test
fun upTransitionSceneKey_deviceLocked_lockscreen() =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt
index f26a9db56450..6986cf8ee7dc 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModelTest.kt
@@ -57,7 +57,7 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@RunWithLooper
@EnableSceneContainer
-class QuickSettingsSceneActionsViewModelTest : SysuiTestCase() {
+class QuickSettingsUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
@@ -67,7 +67,7 @@ class QuickSettingsSceneActionsViewModelTest : SysuiTestCase() {
private val sceneBackInteractor = kosmos.sceneBackInteractor
private val sceneContainerStartable = kosmos.sceneContainerStartable
- private lateinit var underTest: QuickSettingsSceneActionsViewModel
+ private lateinit var underTest: QuickSettingsUserActionsViewModel
@Before
fun setUp() {
@@ -75,7 +75,7 @@ class QuickSettingsSceneActionsViewModelTest : SysuiTestCase() {
sceneContainerStartable.start()
underTest =
- QuickSettingsSceneActionsViewModel(
+ QuickSettingsUserActionsViewModel(
qsSceneAdapter = qsFlexiglassAdapter,
sceneBackInteractor = sceneBackInteractor,
)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index f365afbfcc06..4f7c01358a7f 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -49,7 +49,7 @@ import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.Flags
import com.android.systemui.flags.fakeFeatureFlagsClassic
-import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneActionsViewModel
+import com.android.systemui.keyguard.ui.viewmodel.LockscreenUserActionsViewModel
import com.android.systemui.kosmos.testScope
import com.android.systemui.lifecycle.activateIn
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
@@ -65,10 +65,10 @@ import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.ui.viewmodel.ShadeSceneActionsViewModel
import com.android.systemui.shade.ui.viewmodel.ShadeSceneContentViewModel
-import com.android.systemui.shade.ui.viewmodel.shadeSceneActionsViewModel
+import com.android.systemui.shade.ui.viewmodel.ShadeUserActionsViewModel
import com.android.systemui.shade.ui.viewmodel.shadeSceneContentViewModel
+import com.android.systemui.shade.ui.viewmodel.shadeUserActionsViewModel
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.telephony.data.repository.fakeTelephonyRepository
@@ -145,8 +145,8 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
private lateinit var bouncerActionButtonInteractor: BouncerActionButtonInteractor
private lateinit var bouncerSceneContentViewModel: BouncerSceneContentViewModel
- private val lockscreenSceneActionsViewModel by lazy {
- LockscreenSceneActionsViewModel(
+ private val mLockscreenUserActionsViewModel by lazy {
+ LockscreenUserActionsViewModel(
deviceEntryInteractor = deviceEntryInteractor,
communalInteractor = communalInteractor,
shadeInteractor = kosmos.shadeInteractor,
@@ -154,7 +154,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
}
private lateinit var shadeSceneContentViewModel: ShadeSceneContentViewModel
- private lateinit var shadeSceneActionsViewModel: ShadeSceneActionsViewModel
+ private lateinit var mShadeUserActionsViewModel: ShadeUserActionsViewModel
private val powerInteractor by lazy { kosmos.powerInteractor }
@@ -191,14 +191,14 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
bouncerSceneContentViewModel = kosmos.bouncerSceneContentViewModel
shadeSceneContentViewModel = kosmos.shadeSceneContentViewModel
- shadeSceneActionsViewModel = kosmos.shadeSceneActionsViewModel
+ mShadeUserActionsViewModel = kosmos.shadeUserActionsViewModel
val startable = kosmos.sceneContainerStartable
startable.start()
- lockscreenSceneActionsViewModel.activateIn(testScope)
+ mLockscreenUserActionsViewModel.activateIn(testScope)
shadeSceneContentViewModel.activateIn(testScope)
- shadeSceneActionsViewModel.activateIn(testScope)
+ mShadeUserActionsViewModel.activateIn(testScope)
bouncerSceneContentViewModel.activateIn(testScope)
sceneContainerViewModel.activateIn(testScope)
@@ -229,7 +229,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
@Test
fun swipeUpOnLockscreen_enterCorrectPin_unlocksDevice() =
testScope.runTest {
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
@@ -250,7 +250,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
testScope.runTest {
setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Gone)
@@ -262,7 +262,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
@Test
fun swipeUpOnShadeScene_withAuthMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
testScope.runTest {
- val actions by collectLastValue(shadeSceneActionsViewModel.actions)
+ val actions by collectLastValue(mShadeUserActionsViewModel.actions)
val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
assertCurrentScene(Scenes.Lockscreen)
@@ -283,7 +283,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
@Test
fun swipeUpOnShadeScene_withAuthMethodSwipe_lockscreenDismissed_goesToGone() =
testScope.runTest {
- val actions by collectLastValue(shadeSceneActionsViewModel.actions)
+ val actions by collectLastValue(mShadeUserActionsViewModel.actions)
val canSwipeToEnter by collectLastValue(deviceEntryInteractor.canSwipeToEnter)
val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
@@ -369,7 +369,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
fun swipeUpOnLockscreenWhileUnlocked_dismissesLockscreen() =
testScope.runTest {
unlockDevice()
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Gone)
@@ -392,7 +392,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
fun dismissingIme_whileOnPasswordBouncer_navigatesToLockscreen() =
testScope.runTest {
setAuthMethod(AuthenticationMethodModel.Password)
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
@@ -411,7 +411,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
fun bouncerActionButtonClick_opensEmergencyServicesDialer() =
testScope.runTest {
setAuthMethod(AuthenticationMethodModel.Password)
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
@@ -432,7 +432,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
testScope.runTest {
setAuthMethod(AuthenticationMethodModel.Password)
startPhoneCall()
- val actions by collectLastValue(lockscreenSceneActionsViewModel.actions)
+ val actions by collectLastValue(mLockscreenUserActionsViewModel.actions)
val upDestinationSceneKey =
(actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
index b52627570246..03106eca1f63 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModelTest.kt
@@ -43,17 +43,17 @@ import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
-class GoneSceneActionsViewModelTest : SysuiTestCase() {
+class GoneUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
private val shadeRepository by lazy { kosmos.shadeRepository }
- private lateinit var underTest: GoneSceneActionsViewModel
+ private lateinit var underTest: GoneUserActionsViewModel
@Before
fun setUp() {
underTest =
- GoneSceneActionsViewModel(
+ GoneUserActionsViewModel(
shadeInteractor = kosmos.shadeInteractor,
)
underTest.activateIn(testScope)
@@ -62,21 +62,21 @@ class GoneSceneActionsViewModelTest : SysuiTestCase() {
@Test
fun downTransitionKey_splitShadeEnabled_isGoneToSplitShade() =
testScope.runTest {
- val destinationScenes by collectLastValue(underTest.actions)
+ val userActions by collectLastValue(underTest.actions)
shadeRepository.setShadeLayoutWide(true)
runCurrent()
- assertThat(destinationScenes?.get(Swipe(SwipeDirection.Down))?.transitionKey)
+ assertThat(userActions?.get(Swipe(SwipeDirection.Down))?.transitionKey)
.isEqualTo(ToSplitShade)
}
@Test
fun downTransitionKey_splitShadeDisabled_isNull() =
testScope.runTest {
- val destinationScenes by collectLastValue(underTest.actions)
+ val userActions by collectLastValue(underTest.actions)
shadeRepository.setShadeLayoutWide(false)
runCurrent()
- assertThat(destinationScenes?.get(Swipe(SwipeDirection.Down))?.transitionKey).isNull()
+ assertThat(userActions?.get(Swipe(SwipeDirection.Down))?.transitionKey).isNull()
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModelTest.kt
index 900f2a464588..972afb58352d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModelTest.kt
@@ -42,12 +42,12 @@ import org.junit.runner.RunWith
@SmallTest
@RunWith(AndroidJUnit4::class)
-class SceneActionsViewModelTest : SysuiTestCase() {
+class UserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
- private val underTest = FakeSceneActionsViewModel()
+ private val underTest = FakeUserActionsViewModel()
@Test
fun actions_emptyBeforeActivation() =
@@ -115,7 +115,7 @@ class SceneActionsViewModelTest : SysuiTestCase() {
assertThat(actions).isEmpty()
}
- private class FakeSceneActionsViewModel : SceneActionsViewModel() {
+ private class FakeUserActionsViewModel : UserActionsViewModel() {
val upstream = MutableStateFlow<Map<UserAction, UserActionResult>>(emptyMap())
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
index a931e656c3c6..9f3e126ed1e8 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelTest.kt
@@ -64,7 +64,7 @@ import org.junit.runner.RunWith
@TestableLooper.RunWithLooper
@EnableSceneContainer
@DisableFlags(DualShade.FLAG_NAME)
-class ShadeSceneActionsViewModelTest : SysuiTestCase() {
+class ShadeUserActionsViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
private val testScope = kosmos.testScope
@@ -72,7 +72,7 @@ class ShadeSceneActionsViewModelTest : SysuiTestCase() {
private val shadeRepository by lazy { kosmos.shadeRepository }
private val qsSceneAdapter by lazy { kosmos.fakeQSSceneAdapter }
- private val underTest: ShadeSceneActionsViewModel by lazy { kosmos.shadeSceneActionsViewModel }
+ private val underTest: ShadeUserActionsViewModel by lazy { kosmos.shadeUserActionsViewModel }
@Before
fun setUp() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
index 75ecb2c5307c..beba16229c12 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinatorTest.java
@@ -133,7 +133,8 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
mVisibilityLocationProvider,
mVisualStabilityProvider,
mWakefulnessLifecycle,
- mKosmos.getCommunalInteractor(),
+ mKosmos.getCommunalSceneInteractor(),
+ mKosmos.getShadeInteractor(),
mKosmos.getKeyguardTransitionInteractor(),
mLogger);
mCoordinator.attach(mNotifPipeline);
@@ -561,11 +562,12 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
@Test
public void testCommunalShowingWillNotSuppressReordering() {
- // GIVEN panel is expanded and communal is showing
+ // GIVEN panel is expanded, communal is showing, and QS is collapsed
setPulsing(false);
setFullyDozed(false);
setSleepy(false);
setPanelExpanded(true);
+ setQsExpanded(false);
setCommunalShowing(true);
// Reordering should be allowed
@@ -573,6 +575,20 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
}
@Test
+ public void testQsExpandedOverCommunalWillSuppressReordering() {
+ // GIVEN panel is expanded and communal is showing, but QS is expanded
+ setPulsing(false);
+ setFullyDozed(false);
+ setSleepy(false);
+ setPanelExpanded(true);
+ setQsExpanded(true);
+ setCommunalShowing(true);
+
+ // Reordering should not be allowed
+ assertFalse(mNotifStabilityManager.isEntryReorderingAllowed(mEntry));
+ }
+
+ @Test
public void testQueryingEntryReorderingButNotReportingReorderSuppressedDoesNotInvalidate() {
// GIVEN visual stability is being maintained b/c panel is expanded
setPulsing(false);
@@ -631,7 +647,12 @@ public class VisualStabilityCoordinatorTest extends SysuiTestCase {
new ObservableTransitionState.Idle(
isShowing ? CommunalScenes.Communal : CommunalScenes.Blank)
);
- mKosmos.getCommunalRepository().setTransitionState(showingFlow);
+ mKosmos.getCommunalSceneInteractor().setTransitionState(showingFlow);
+ mTestScope.getTestScheduler().runCurrent();
+ }
+
+ private void setQsExpanded(boolean isExpanded) {
+ mKosmos.getShadeRepository().setQsExpansion(isExpanded ? 1.0f : 0.0f);
mTestScope.getTestScheduler().runCurrent();
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
index a6fdd0391787..b5dbc3fe1b4d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositorySwitcherTest.kt
@@ -22,8 +22,6 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.demomode.DemoMode
import com.android.systemui.demomode.DemoModeController
-import com.android.systemui.flags.FakeFeatureFlagsClassic
-import com.android.systemui.flags.Flags
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
@@ -73,11 +71,6 @@ class WifiRepositorySwitcherTest : SysuiTestCase() {
private val demoModelFlow = MutableStateFlow<FakeWifiEventModel?>(null)
private val mainExecutor = FakeExecutor(FakeSystemClock())
- private val featureFlags =
- FakeFeatureFlagsClassic().also {
- it.set(Flags.INSTANT_TETHER, true)
- it.set(Flags.WIFI_SECONDARY_NETWORKS, true)
- }
private val testDispatcher = UnconfinedTestDispatcher()
private val testScope = TestScope(testDispatcher)
@@ -93,7 +86,6 @@ class WifiRepositorySwitcherTest : SysuiTestCase() {
realImpl =
WifiRepositoryImpl(
- featureFlags,
testScope.backgroundScope,
mainExecutor,
testDispatcher,
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt
index 509f022310d0..84f39afee834 100644
--- a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt
+++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceConfigPlugin.kt
@@ -21,4 +21,6 @@ package com.android.systemui.plugins
interface BcSmartspaceConfigPlugin {
/** Gets default date/weather disabled status. */
val isDefaultDateWeatherDisabled: Boolean
+ /** Gets if Smartspace should use ViewPager2 */
+ val isViewPager2Enabled: Boolean
}
diff --git a/packages/SystemUI/res/color/brightness_slider_track.xml b/packages/SystemUI/res/color/brightness_slider_track.xml
deleted file mode 100644
index 6028769f3789..000000000000
--- a/packages/SystemUI/res/color/brightness_slider_track.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?><!--
- ~ Copyright (C) 2024 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/system_neutral2_500" android:lStar="40" />
-</selector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/arrow_pointing_down.xml b/packages/SystemUI/res/drawable/arrow_pointing_down.xml
index be39683cd78d..ca573c768765 100644
--- a/packages/SystemUI/res/drawable/arrow_pointing_down.xml
+++ b/packages/SystemUI/res/drawable/arrow_pointing_down.xml
@@ -19,7 +19,7 @@
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
- android:tint="?attr/colorControlNormal">
+ android:tint="?android:attr/textColorPrimary">
<path
android:fillColor="@android:color/white"
android:pathData="M5.41,7.59L4,9l8,8 8,-8 -1.41,-1.41L12,14.17" />
diff --git a/packages/SystemUI/res/drawable/brightness_bar.xml b/packages/SystemUI/res/drawable/brightness_bar.xml
index 2afe164ab5c5..3d1c1fbd6ce7 100644
--- a/packages/SystemUI/res/drawable/brightness_bar.xml
+++ b/packages/SystemUI/res/drawable/brightness_bar.xml
@@ -21,7 +21,7 @@
android:viewportHeight="48">
<path
android:pathData="M2,22L302,22A2,2 0,0 1,304 24L304,24A2,2 0,0 1,302 26L2,26A2,2 0,0 1,0 24L0,24A2,2 0,0 1,2 22z"
- android:fillColor="@color/brightness_slider_track"/>
+ android:fillColor="?androidprv:attr/customColorShadeInactive"/>
<path
android:pathData="M24,0L205.71,0A24,24 0,0 1,229.71 24L229.71,24A24,24 0,0 1,205.71 48L24,48A24,24 0,0 1,0 24L0,24A24,24 0,0 1,24 0z"
android:fillColor="?attr/shadeActive"/>
diff --git a/packages/SystemUI/res/drawable/brightness_progress_drawable.xml b/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
index cae9d6b0513e..ec15b10851c5 100644
--- a/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
+++ b/packages/SystemUI/res/drawable/brightness_progress_drawable.xml
@@ -15,6 +15,7 @@
~ limitations under the License.
-->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:paddingMode="stack" >
<item android:id="@android:id/background"
android:gravity="center_vertical|fill_horizontal">
@@ -24,7 +25,7 @@
<shape>
<size android:height="@dimen/rounded_slider_track_width" />
<corners android:radius="@dimen/rounded_slider_track_corner_radius" />
- <solid android:color="@color/brightness_slider_track" />
+ <solid android:color="?androidprv:attr/customColorShadeInactive" />
</shape>
</inset>
</item>
diff --git a/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml b/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml
index e06bfdc500da..368fe829cf9f 100644
--- a/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml
+++ b/packages/SystemUI/res/layout/alert_dialog_button_bar_systemui.xml
@@ -52,7 +52,7 @@
<Button
android:id="@android:id/button1"
style="?android:attr/buttonBarPositiveButtonStyle"
- android:layout_marginStart="8dp"
+ android:layout_marginStart="@dimen/dialog_button_side_margin"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</com.android.internal.widget.ButtonBarLayout>
diff --git a/packages/SystemUI/res/layout/ongoing_activity_chip.xml b/packages/SystemUI/res/layout/ongoing_activity_chip.xml
index 154397d2b4a1..690a89a044b7 100644
--- a/packages/SystemUI/res/layout/ongoing_activity_chip.xml
+++ b/packages/SystemUI/res/layout/ongoing_activity_chip.xml
@@ -17,7 +17,6 @@
the chip. -->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/ongoing_activity_chip"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|start"
diff --git a/packages/SystemUI/res/layout/screen_share_dialog.xml b/packages/SystemUI/res/layout/screen_share_dialog.xml
index aa083ad9fdea..0533c7e3fc50 100644
--- a/packages/SystemUI/res/layout/screen_share_dialog.xml
+++ b/packages/SystemUI/res/layout/screen_share_dialog.xml
@@ -64,30 +64,27 @@
android:layout_height="wrap_content"
android:text="@string/screenrecord_permission_dialog_warning_entire_screen"
style="@style/TextAppearance.Dialog.Body.Message"
- android:gravity="start"/>
+ android:gravity="start"
+ android:textAlignment="gravity"/>
<!-- Buttons -->
<com.android.internal.widget.ButtonBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
- android:layout_marginTop="@dimen/screenrecord_buttons_margin_top">
+ android:layout_marginTop="@dimen/screenrecord_buttons_margin_top"
+ android:gravity="end">
<Button
android:id="@android:id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="0"
android:text="@string/cancel"
style="@style/Widget.Dialog.Button.BorderButton" />
- <Space
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"/>
<Button
android:id="@android:id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="0"
+ android:layout_marginStart="@dimen/dialog_button_side_margin"
android:text="@string/screenrecord_continue"
style="@style/Widget.Dialog.Button" />
</com.android.internal.widget.ButtonBarLayout>
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index 4247c7eef0d0..ee75b3145aef 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -99,7 +99,10 @@
android:gravity="center_vertical|start"
/>
- <include layout="@layout/ongoing_activity_chip" />
+ <include layout="@layout/ongoing_activity_chip"
+ android:id="@+id/ongoing_activity_chip_primary"/>
+
+ <!-- TODO(b/364653005): Add a second activity chip. -->
<com.android.systemui.statusbar.AlphaOptimizedFrameLayout
android:id="@+id/notification_icon_area"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 7251f03024e3..a1be54cf00e7 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Gebruik Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Gekoppel"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Oudiodeling"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gestoor"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ontkoppel"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiveer"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliet, goeie toestand"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding is beskikbaar"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelliet-SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Noodoproepe of SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Pret vir party mense, maar nie vir almal nie"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Stelsel-UI-ontvanger gee jou ekstra maniere om die Android-gebruikerkoppelvlak in te stel en te pasmaak. Hierdie eksperimentele kenmerke kan in toekomstige uitreikings verander, breek of verdwyn. Gaan versigtig voort."</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 54fb216d99ae..23f376631899 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ብሉቱዝን ይጠቀሙ"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ተገናኝቷል"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"የድምጽ ማጋራት"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ተቀምጧል"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ግንኙነትን አቋርጥ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ያግብሩ"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ሳተላይት፣ ጥሩ ግንኙነት"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ሳተላይት፣ ግንኙነት አለ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ሳተላይት ኤስኦኤስ"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"የአደጋ ጥሪዎች ወይም ኤስኦኤስ"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"የስራ መገለጫ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ለአንዳንዶች አስደሳች ቢሆንም ለሁሉም አይደለም"</string>
<string name="tuner_warning" msgid="1861736288458481650">"የስርዓት በይነገጽ መቃኛ የAndroid ተጠቃሚ በይነገጹን የሚነካኩበት እና የሚያበጁበት ተጨማሪ መንገዶች ይሰጠዎታል። እነዚህ የሙከራ ባህሪዎች ወደፊት በሚኖሩ ልቀቶች ላይ ሊለወጡ፣ ሊሰበሩ ወይም ሊጠፉ ይችላሉ። ከጥንቃቄ ጋር ወደፊት ይቀጥሉ።"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 6866ed717d2b..0ac0d03b190d 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"استخدام البلوتوث"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"متّصل"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"مشاركة الصوت"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"محفوظ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"إلغاء الربط"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"تفعيل"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"قمر صناعي، الاتصال جيد"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"قمر صناعي، الاتصال متوفّر"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"اتصالات الطوارئ بالقمر الصناعي"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"مكالمات الطوارئ أو ميزة \"اتصالات طوارئ بالقمر الصناعي\""</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ملف العمل"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"متعة للبعض وليس للجميع"</string>
<string name="tuner_warning" msgid="1861736288458481650">"‏توفر لك أداة ضبط واجهة مستخدم النظام طرقًا إضافية لتعديل واجهة مستخدم Android وتخصيصها. ويمكن أن تطرأ تغييرات على هذه الميزات التجريبية أو يمكن أن تتعطل هذه الميزات أو تختفي في الإصدارات المستقبلية. عليك متابعة الاستخدام مع توخي الحذر."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 0c8ef431fff9..a770c61e994c 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ব্লুটুথ ব্যৱহাৰ কৰক"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"সংযুক্ত আছে"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"অডিঅ’ শ্বেয়াৰ কৰা"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ছেভ কৰা হৈছে"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"সংযোগ বিচ্ছিন্ন কৰক"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"সক্ৰিয় কৰক"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"উপগ্ৰহ, ভাল সংযোগ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"উপগ্ৰহ, সংযোগ উপলব্ধ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"উপগ্ৰহ SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"জৰুৰীকালীন কল বা SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"কিছুমানৰ বাবে আমোদজনক হয় কিন্তু সকলোৰে বাবে নহয়"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tunerএ আপোনাক Android ব্যৱহাৰকাৰী ইণ্টাৰফেইচ সলনি কৰিবলৈ আৰু নিজৰ উপযোগিতা অনুসৰি ব্যৱহাৰ কৰিবলৈ অতিৰিক্ত সুবিধা প্ৰদান কৰে। এই পৰীক্ষামূলক সুবিধাসমূহ সলনি হ\'ব পাৰে, সেইবোৰে কাম নকৰিব পাৰে বা আগন্তুক সংস্কৰণসমূহত সেইবোৰ অন্তৰ্ভুক্ত কৰা নহ’ব পাৰে। সাৱধানেৰে আগবাঢ়ক।"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index df3ecf7d8b3c..cd7bbaf4cf1f 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-u açın"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Qoşulub"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio paylaşma"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Yadda saxlandı"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"əlaqəni kəsin"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivləşdirin"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Peyk, bağlantı yaxşıdır"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Peyk, bağlantı var"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Təcili peyk bağlantısı"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Təcili zənglər və ya SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Hamı üçün deyil, bəziləri üçün əyləncəli"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android istifadəçi interfeysini dəyişdirmək və fərdiləşdirmək üçün Sizə ekstra yollar təklif edir."</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 9198710eed09..25ecce548dd1 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Deljenje zvuka"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sačuvano"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekinite vezu"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivirajte"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, veza je dobra"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Hitna pomoć preko satelita"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hitni pozivi ili hitna pomoć"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Tjuner za korisnički interfejs sistema vam pruža dodatne načine za podešavanje i prilagođavanje Android korisničkog interfejsa. Ove eksperimentalne funkcije mogu da se promene, otkažu ili nestanu u budućim izdanjima. Budite oprezni."</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index c5c2912f8b3e..5ea062112198 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Выкарыстоўваць Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Падключана"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Абагульванне аўдыя"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Захавана"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"адключыць"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"актываваць"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спадарожнікавая сувязь, добрае падключэнне"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спадарожнікавая сувязь, падключэнне даступнае"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Экстраннае спадарожнікавае падключэнне"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Экстранныя выклікі або экстраннае спадарожнікавае падключэнне"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Працоўны профіль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Цікава для некаторых, але не для ўсіх"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Наладка сістэмнага інтэрфейсу карыстальніка дае вам дадатковыя спосабы наладжвання і дапасоўвання карыстальніцкага інтэрфейсу Android. Гэтыя эксперыментальныя функцыі могуць змяніцца, перастаць працаваць або знікнуць у будучых версіях. Карыстайцеся з асцярожнасцю."</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 58f492e55b9d..ee118632f6b9 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Използване на Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Установена е връзка"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Споделяне на звука"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Запазено"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекратяване на връзката"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активиране"</string>
@@ -390,7 +392,7 @@
<string name="performance" msgid="6552785217174378320">"Ефективност"</string>
<string name="user_interface" msgid="3712869377953950887">"Потребителски интерфейс"</string>
<string name="thermal" msgid="6758074791325414831">"Температура"</string>
- <string name="custom" msgid="3337456985275158299">"Персонализирано"</string>
+ <string name="custom" msgid="3337456985275158299">"Персонализиране"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Настройки за персонализираната следа"</string>
<string name="restore_default" msgid="5259420807486239755">"Възстановяване на стандартната настройка"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Режим за работа с една ръка"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Сателит, добра връзка"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, налице е връзка"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS чрез сателит"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Спешни обаждания или SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Потребителски профил в Work"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забавно – но не за всички"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Тунерът на системния потребителски интерфейс ви предоставя допълнителни възможности за прецизиране и персонализиране на практическата работа с Android. Тези експериментални функции може да се променят, повредят или да изчезнат в бъдещите версии. Действайте внимателно."</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index c9e24f0bb126..2536cb74a240 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ব্লুটুথ ব্যবহার করুন"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"কানেক্ট করা আছে"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"অডিও শেয়ারিং"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"সেভ করা আছে"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ডিসকানেক্ট করুন"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"চালু করুন"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"স্যাটেলাইট, ভালো কানেকশন"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"স্যাটেলাইট, কানেকশন উপলভ্য আছে"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"স্যাটেলাইট SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"জরুরি কল বা SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"কাজের প্রোফাইল"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"কিছু ব্যক্তির জন্য মজাদার কিন্তু সকলের জন্য নয়"</string>
<string name="tuner_warning" msgid="1861736288458481650">"এই পরীক্ষামূলক বৈশিষ্ট্যগুলি ভবিষ্যতের সংস্করণগুলির মধ্যে পরিবর্তিত, বিভাজিত এবং অদৃশ্য হয়ে যেতে পারে৷ সাবধানতার সাথে এগিয়ে যান৷ সিস্টেম UI টিউনার আপনাকে Android ব্যবহারকারী ইন্টারফেসের সূক্ষ্ম সমন্বয় এবং কাস্টমাইজ করার অতিরিক্ত উপায়গুলি প্রদান করে৷"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 894956703753..43ae5c73bc06 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Dijeljenje zvuka"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sačuvano"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekid veze"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviranje"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra veza"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Hitna pomoć putem satelita"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hitni pozivi ili pomoć"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Radni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Podešavač za korisnički interfejs sistema vam omogućava dodatne načine da podesite i prilagodite Androidov interfejs. Ove eksperimentalne funkcije se u budućim verzijama mogu mijenjati, kvariti ili nestati. Budite oprezni."</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 74cce98dde5b..187e75e27e05 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -110,7 +110,7 @@
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Vols gravar la pantalla?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Grava una aplicació"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"Grava tota la pantalla"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Quan graves tota la pantalla, es grava tot el que es mostra en pantalla. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos, i l\'àudio i el vídeo."</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Quan graves tota la pantalla, es grava tot el que es mostra en pantalla. Per aquest motiu, ves amb compte amb elements com les contrasenyes, les dades de pagament, els missatges, les fotos, i l\'àudio i el vídeo."</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Quan graves una aplicació, es grava tot el que es mostra o es reprodueix en aquesta aplicació. Per aquest motiu, ves amb compte amb les contrasenyes, les dades de pagament, els missatges, les fotos, i l\'àudio i el vídeo."</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Grava la pantalla"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"Tria una aplicació per gravar"</string>
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Utilitza el Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connectat"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartició d\'àudio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Desat"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconnecta"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activa"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satèl·lit, bona connexió"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satèl·lit, connexió disponible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS per satèl·lit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Trucades d\'emergència o SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de treball"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversió per a uns quants, però no per a tothom"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El Personalitzador d\'interfície d\'usuari presenta opcions addicionals per canviar i personalitzar la interfície d\'usuari d\'Android. És possible que aquestes funcions experimentals canviïn, deixin de funcionar o desapareguin en versions futures. Continua amb precaució."</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 8c0571ef5dc9..13e03778b192 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Používat Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Připojeno"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Sdílení zvuku"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Uloženo"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"odpojit"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivovat"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobré připojení"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, připojení je k dispozici"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS přes satelit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Tísňová volání nebo SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovní profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zábava, která není pro každého"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Nástroj na ladění uživatelského rozhraní systému vám nabízí další způsoby, jak si vyladit a přizpůsobit uživatelské rozhraní Android. Tyto experimentální funkce mohou v dalších verzích chybět, nefungovat nebo být změněny. Postupujte proto prosím opatrně."</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 9b72478b7259..4ba9fe9bb375 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Brug Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Der er oprettet forbindelse"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Lyddeling"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gemt"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"afbryd forbindelse"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivér"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit – god forbindelse"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit – forbindelsen er tilgængelig"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-meldinger via satellit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Nødopkald eller SOS-meldinger via satellit"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbejdsprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Sjovt for nogle, men ikke for alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner giver dig flere muligheder for at justere og tilpasse Android-brugerfladen. Disse eksperimentelle funktioner kan ændres, gå i stykker eller forsvinde i fremtidige udgivelser. Vær forsigtig, hvis du fortsætter."</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 7bfdf6704551..7a8d06c8b81b 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth verwenden"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Verbunden"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audiofreigabe"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gespeichert"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"Verknüpfung aufheben"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivieren"</string>
@@ -629,7 +631,7 @@
<string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Einstellungen"</string>
<string name="volume_panel_captioning_title" msgid="5984936949147684357">"Automatische Untertitel"</string>
<string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Auf verträglichere Lautstärke eingestellt"</string>
- <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Die Kopfhörerlautstärke war länger als empfohlen hoch eingestellt"</string>
+ <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Die Kopfhörer sind schon länger als empfohlen auf hohe Lautstärke eingestellt"</string>
<string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Die Kopfhörerlautstärke hat für diese Woche das Sicherheitslimit überschritten"</string>
<string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Weiterhören"</string>
<string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Leiser stellen"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit, Verbindung gut"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, Verbindung verfügbar"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Notruf über Satellit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Notrufe oder SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Arbeitsprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Für einige ein Vergnügen, aber nicht für alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Mit System UI Tuner erhältst du zusätzliche Möglichkeiten, die Android-Benutzeroberfläche anzupassen. Achtung: Diese Testfunktionen können sich ändern, abstürzen oder in zukünftigen Versionen verschwinden."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index ed17959ea8f0..015d625a000a 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Χρήση Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Συνδέθηκε"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Κοινή χρήση ήχου"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Αποθηκεύτηκε"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"αποσύνδεση"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ενεργοποίηση"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Δορυφορική, καλή σύνδεση"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Δορυφορική, διαθέσιμη σύνδεση"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Δορυφορικό SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Κλήσεις έκτακτης ανάγκης ή SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Προφίλ εργασίας"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Διασκέδαση για ορισμένους, αλλά όχι για όλους"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Το System UI Tuner σάς προσφέρει επιπλέον τρόπους για να τροποποιήσετε και να προσαρμόσετε τη διεπαφή χρήστη Android. Αυτές οι πειραματικές λειτουργίες ενδέχεται να τροποποιηθούν, να παρουσιάσουν σφάλματα ή να καταργηθούν σε μελλοντικές εκδόσεις. Συνεχίστε με προσοχή."</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 0565be88e855..bab9a508e947 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Emergency calls or SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 17642f7b3b58..67ce124b88d3 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio Sharing"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 0565be88e855..bab9a508e947 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Emergency calls or SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 0565be88e855..bab9a508e947 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Use Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connected"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio sharing"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saved"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnect"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activate"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, good connection"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, connection available"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Emergency calls or SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work profile"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Fun for some but not for all"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner gives you extra ways to tweak and customise the Android user interface. These experimental features may change, break or disappear in future releases. Proceed with caution."</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index d31d328b4816..4317f86de6f6 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎Use Bluetooth‎‏‎‎‏‎"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‎‏‏‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎Connected‎‏‎‎‏‎"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‎‏‏‎‎‎‏‎‎‎‎‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‏‎‎Audio Sharing‎‏‎‎‏‎"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‎‎‎‏‏‎‎‎‏‏‎‏‏‎‎‎‏‎‏‎‏‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‎‎‏‏‎‎‎‏‏‏‎‏‏‎‎‏‎‏‎Saved‎‏‎‎‏‎"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‏‏‏‎‎disconnect‎‏‎‎‏‎"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‏‎‎‎‏‏‎‏‎‎‏‎‏‏‎‏‏‎activate‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 53c38e2d2eef..b9cfbaa3da82 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -110,7 +110,7 @@
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"¿Quieres grabar la pantalla?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Grabar una app"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"Grabar toda la pantalla"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Cuando grabes toda la pantalla, se registrará todo lo que se muestre en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Cuando grabes toda la pantalla, se grabará todo lo que se muestre en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Cuando grabes una app, se registrará todo lo que se muestre o reproduzca en ella. Por lo tanto, debes tener cuidado con contraseñas, detalles de pagos, mensajes, fotos, audios y videos."</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Grabar pantalla"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"Elige una app para grabar"</string>
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Uso compartido de audio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, buena conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Llamadas de emergencia o SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión solo para algunas personas"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El sintonizador de IU del sistema te brinda más formas para editar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, dejar de funcionar o no incluirse en futuras versiones. Procede con precaución."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 0bebccf9b199..b39295946798 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartir audio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
@@ -390,7 +392,7 @@
<string name="performance" msgid="6552785217174378320">"Rendimiento"</string>
<string name="user_interface" msgid="3712869377953950887">"Interfaz de usuario"</string>
<string name="thermal" msgid="6758074791325414831">"Temperatura"</string>
- <string name="custom" msgid="3337456985275158299">"Otro"</string>
+ <string name="custom" msgid="3337456985275158299">"Config. personalizada"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Ajustes de traza personalizados"</string>
<string name="restore_default" msgid="5259420807486239755">"Restaurar ajustes predeterminados"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modo Una mano"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, buena conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión disponible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Llamadas de emergencia o SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabajo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión solo para algunos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"El configurador de UI del sistema te ofrece otras formas de modificar y personalizar la interfaz de usuario de Android. Estas funciones experimentales pueden cambiar, fallar o desaparecer en futuras versiones. Te recomendamos que tengas cuidado."</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index b2ffa80f6ad3..c56d10100fdd 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Kasuta Bluetoothi"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ühendatud"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Heli jagamine"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvestatud"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"katkesta ühendus"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiveeri"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliit, hea ühendus"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliit, ühendus on saadaval"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelliit-SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hädaabikõned või SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Tööprofiil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kõik ei pruugi sellest rõõmu tunda"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Süsteemi kasutajaliidese tuuner pakub täiendavaid võimalusi Androidi kasutajaliidese muutmiseks ja kohandamiseks. Need katselised funktsioonid võivad muutuda, rikki minna või tulevastest versioonidest kaduda. Olge jätkamisel ettevaatlik."</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index d8cff19f5887..ccebe2bd0b5c 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Erabili Bluetootha"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Konektatuta"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audioa partekatzea"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gordeta"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"deskonektatu"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktibatu"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelitea, konexio ona"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelitea, konexioa erabilgarri"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelite bidezko SOS komunikazioa"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Larrialdi-deiak edo SOS komunikazioa"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Laneko profila"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Dibertsioa batzuentzat, baina ez guztientzat"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistemaren erabiltzaile-interfazearen konfiguratzaileak Android erabiltzaile-interfazea moldatzeko eta pertsonalizatzeko modu gehiago eskaintzen dizkizu. Baliteke eginbide esperimental horiek hurrengo kaleratzeetan aldatuta, etenda edo desagertuta egotea. Kontuz erabili."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 5b17c4447d52..7e622cfc190f 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"استفاده از بلوتوث"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"متصل"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"اشتراک صدا"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ذخیره‌شده"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"قطع اتصال"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"فعال کردن"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ماهواره، اتصال خوب است"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ماهواره، اتصال دردسترس است"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"درخواست کمک ماهواره‌ای"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"تماس اضطراری یا درخواست کمک اضطراری"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"نمایه کاری"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"برای بعضی افراد سرگرم‌کننده است اما نه برای همه"</string>
<string name="tuner_warning" msgid="1861736288458481650">"‏«تنظیم‌کننده واسط کاربری سیستم» روش‌های بیشتری برای تنظیم دقیق و سفارشی کردن واسط کاربری Android در اختیار شما قرار می‌دهد. ممکن است این ویژگی‌های آزمایشی تغییر کنند، خراب شوند یا در نسخه‌های آینده جود نداشته باشند. با احتیاط ادامه دهید."</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 9244becd8338..4d7f41a3d1d5 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Käytä Bluetoothia"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Yhdistetty"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audionjako"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Tallennettu"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"katkaise yhteys"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivoi"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliitti, hyvä yhteys"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliitti, yhteys saatavilla"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hätäpuhelut tai Satellite SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Työprofiili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Ei sovellu kaikkien käyttöön"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner antaa lisämahdollisuuksia Android-käyttöliittymän muokkaamiseen. Nämä kokeelliset ominaisuudet voivat muuttua, lakata toimimasta tai kadota milloin tahansa. Jatka omalla vastuullasi."</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 41305af8d455..51dc60f0e015 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Utiliser le Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connecté"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partage audio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Enregistré"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"Déconnecter"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"Activer"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Bonne connexion satellite"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite accessible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS par satellite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Appels d\'urgence ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur d\'Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 4df98cf1864d..bd6c6645508d 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -110,7 +110,7 @@
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Enregistrer l\'écran ?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Enregistrer une appli"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"Enregistrer tout l\'écran"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Lorsque vous enregistrez tout votre écran, tout ce qui s\'affiche sur celui-ci est enregistré. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Lorsque vous enregistrez l\'intégralité de votre écran, tout ce qui s\'y affiche est enregistré. Faites donc attention aux éléments tels que les mots de passe, les détails du mode de paiement, les messages, les photos, et les contenus audio et vidéo."</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Lorsque vous enregistrez une appli, tout ce qui est affiché ou lu dans celle-ci est enregistré. Faites donc attention aux éléments tels que les mots de passe, détails de mode de paiement, messages, photos et contenus audio et vidéo."</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Enregistrer l\'écran"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"Choisir l\'appli à enregistrer"</string>
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Utiliser le Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Connecté"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partage audio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Enregistré"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"dissocier"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activer"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Bonne connexion satellite"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Connexion satellite disponible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS par satellite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Appels d\'urgence ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil professionnel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Divertissant pour certains, mais pas pour tous"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner vous propose de nouvelles manières d\'adapter et de personnaliser l\'interface utilisateur Android. Ces fonctionnalités expérimentales peuvent être modifiées, cesser de fonctionner ou disparaître dans les versions futures. À utiliser avec prudence."</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 1fe1242bf466..81e96d6f8e2e 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Estableceuse a conexión"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio compartido"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Gardouse"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activar"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, boa conexión"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexión dispoñible"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS por satélite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emerxencia ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de traballo"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversión só para algúns"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O configurador da IU do sistema ofréceche formas adicionais de modificar e personalizar a interface de usuario de Android. Estas funcións experimentais poden cambiar, interromperse ou desaparecer en futuras versións. Continúa con precaución."</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index 7ecc0576f913..ffa8554ff367 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"બ્લૂટૂથનો ઉપયોગ કરો"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"કનેક્ટેડ છે"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ઑડિયો શેરિંગ"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"સાચવેલું"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ડિસ્કનેક્ટ કરો"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"સક્રિય કરો"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"સૅટલાઇટ, સારું કનેક્શન"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"સૅટલાઇટ, કનેક્શન ઉપલબ્ધ છે"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ઇમર્જન્સી સૅટલાઇટ સહાય"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ઇમર્જન્સી કૉલ અથવા SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ઑફિસની પ્રોફાઇલ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"કેટલાક માટે મજા પરંતુ બધા માટે નહીં"</string>
<string name="tuner_warning" msgid="1861736288458481650">"સિસ્ટમ UI ટ્યૂનર તમને Android વપરાશકર્તા ઇન્ટરફેસને ટ્વીક અને કસ્ટમાઇઝ કરવાની વધારાની રીતો આપે છે. ભાવિ રીલિઝેસમાં આ પ્રાયોગિક સુવિધાઓ બદલાઈ, ભંગ અથવા અદૃશ્ય થઈ શકે છે. સાવધાની સાથે આગળ વધો."</string>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index c6a5e572e106..b56b30c3f6b1 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -110,7 +110,7 @@
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"क्या आपको स्क्रीन रिकॉर्ड करनी है?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"एक ऐप्लिकेशन की रिकॉर्डिंग करें"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"पूरी स्क्रीन रिकॉर्ड करें"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"पूरी स्क्रीन रिकॉर्ड करते समय, स्क्रीन पर दिखने वाली हर चीज़ रिकॉर्ड की जाती है. इसलिए, पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, और डिवाइस पर चल रहे ऑडियो और वीडियो को लेकर सावधानी बरतें."</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"पूरी स्क्रीन रिकॉर्ड करते समय, स्क्रीन पर दिखने वाली हर चीज़ रिकॉर्ड की जाती है. इसलिए पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, डिवाइस पर चल रहे ऑडियो और वीडियो, और फ़ोटो जैसी चीज़ों को लेकर सावधानी बरतें."</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"किसी ऐप्लिकेशन को रिकॉर्ड करने के दौरान, उस पर दिख रहा कॉन्टेंट या चल रहा मीडिया दूसरी स्क्रीन पर भी रिकॉर्ड होता है. इसलिए, रिकॉर्ड करते समय पासवर्ड, पेमेंट के तरीके की जानकारी, मैसेज, फ़ोटो, ऑडियो, और वीडियो को लेकर सावधानी बरतें."</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"स्क्रीन रिकॉर्ड करें"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"रिकॉर्ड करने के लिए ऐप्लिकेशन चुनें"</string>
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्लूटूथ इस्तेमाल करें"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट है"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ऑडियो शेयर करने की सुविधा"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेव किया गया"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिसकनेक्ट करें"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"चालू करें"</string>
@@ -628,8 +630,8 @@
<string name="sound_settings" msgid="8874581353127418308">"आवाज़ और वाइब्रेशन"</string>
<string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"सेटिंग"</string>
<string name="volume_panel_captioning_title" msgid="5984936949147684357">"लाइव कैप्शन"</string>
- <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"आवाज़ को कम करके, सुरक्षित लेवल पर सेट कर दिया गया है"</string>
- <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"हेडफ़ोन की आवाज़ सुझाए गए समय से देर तक ज़्यादा रही"</string>
+ <string name="csd_lowered_title" product="default" msgid="2464112924151691129">"आवाज़ को कम करके, सुरक्षित लेवल पर सेट किया गया"</string>
+ <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"हेडफ़ोन की आवाज़ सुझाए गए समय के बाद भी ज़्यादा रही"</string>
<string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"इस हफ़्ते के लिए हेडफ़ोन की आवाज़, सुझाई गई सीमा से ज़्यादा हो गई है"</string>
<string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"सुनना जारी रखें"</string>
<string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"आवाज़ कम करें"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"सैटलाइट कनेक्शन अच्छा है"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सैटलाइट कनेक्शन उपलब्ध है"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"सैटलाइट एसओएस"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"आपातकालीन कॉल या एसओएस"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"वर्क प्रोफ़ाइल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"कुछ के लिए मज़ेदार लेकिन सबके लिए नहीं"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम यूज़र इंटरफ़ेस (यूआई) ट्यूनर, आपको Android यूज़र इंटरफ़ेस में सुधार लाने और उसे अपनी पसंद के हिसाब से बदलने के कुछ और तरीके देता है. प्रयोग के तौर पर इस्तेमाल हो रहीं ये सुविधाएं आगे चल कर रिलीज़ की जा सकती हैं, रोकी जा सकती हैं या दिखाई देना बंद हो सकती हैं. सावधानी से आगे बढ़ें."</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 2edf138cc217..e1b2df26b302 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Koristi Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Zajedničko slušanje"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Spremljeno"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekini vezu"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviraj"</string>
@@ -389,7 +391,7 @@
<string name="qs_record_issue_dropdown_screenrecord" msgid="6396141928484257626">"Snimanje zaslona"</string>
<string name="performance" msgid="6552785217174378320">"Izvedba"</string>
<string name="user_interface" msgid="3712869377953950887">"Korisničko sučelje"</string>
- <string name="thermal" msgid="6758074791325414831">"Termalno"</string>
+ <string name="thermal" msgid="6758074791325414831">"Pregrijavanje"</string>
<string name="custom" msgid="3337456985275158299">"Prilagođeno"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Postavke prilagođenog praćenja"</string>
<string name="restore_default" msgid="5259420807486239755">"Vrati na zadano"</string>
@@ -629,7 +631,7 @@
<string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Postavke"</string>
<string name="volume_panel_captioning_title" msgid="5984936949147684357">"Automatski titlovi"</string>
<string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Glasnoća je stišana na sigurniju razinu"</string>
- <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Glasnoća u slušalicama pojačana je dulje nego što se preporučuje"</string>
+ <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Zvuk u slušalicama bio je preglasan dulje nego što se preporučuje"</string>
<string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Glasnoća slušalica premašila je sigurno ograničenje za ovaj tjedan"</string>
<string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Nastavi slušati"</string>
<string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Stišaj"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra veza"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, veza je dostupna"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS putem satelita"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Hitni pozivi ili SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Poslovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabava za neke, ali ne za sve"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Ugađanje korisničkog sučelja sustava pruža vam dodatne načine za prilagodbu korisničkog sučelja Androida. Te se eksperimentalne značajke mogu promijeniti, prekinuti ili nestati u budućim izdanjima. Nastavite uz oprez."</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 36bae57c5239..f4d34fccea79 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth használata"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Csatlakozva"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Hang megosztása"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Mentve"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"leválasztás"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiválás"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Műhold, jó kapcsolat"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Műhold, van rendelkezésre álló kapcsolat"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Műholdas SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Segélyhívás vagy SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Munkaprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Egyeseknek tetszik, másoknak nem"</string>
<string name="tuner_warning" msgid="1861736288458481650">"A Kezelőfelület-hangoló az Android felhasználói felületének szerkesztéséhez és testreszabásához nyújt további megoldásokat. Ezek a kísérleti funkciók változhatnak vagy megsérülhetnek a későbbi kiadásokban, illetve eltűnhetnek azokból. Körültekintően járjon el."</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 24e90653fa96..3b7855b993c0 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Միացնել Bluetooth-ը"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Միացված է"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Աուդիոյի փոխանցում"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Պահված է"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"անջատել"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ակտիվացնել"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Արբանյակային լավ կապ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Հասանելի է արբանյակային կապ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Շտապ կանչեր կամ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Աշխատանքային պրոֆիլ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Զվարճանք մեկ՝ որոշակի մարդու համար"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Համակարգի ՕՄ-ի կարգավորիչը հնարավորություն է տալիս հարմարեցնել Android-ի օգտատիրոջ միջերեսը: Այս փորձնական գործառույթները կարող են հետագա թողարկումների մեջ փոփոխվել, խափանվել կամ ընդհանրապես չհայտնվել: Եթե շարունակում եք, զգուշացեք:"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index d5f766b09e82..3ddd9f11228f 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Gunakan Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Terhubung"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Berbagi Audio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Disimpan"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"berhenti hubungkan"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktifkan"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, koneksi baik"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, koneksi tersedia"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via Satelit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Panggilan darurat atau SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Tidak semua orang menganggapnya baik"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Penyetel Antarmuka Pengguna Sistem memberikan cara tambahan untuk mengubah dan menyesuaikan antarmuka pengguna Android. Fitur eksperimental ini dapat berubah, rusak, atau menghilang dalam rilis di masa mendatang. Lanjutkan dengan hati-hati."</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index b3291bb93b35..8c57ed195bc4 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Nota Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Tengt"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Hljóði deilt"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Vistað"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"aftengja"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"virkja"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Gervihnöttur, góð tenging"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Gervihnöttur, tenging tiltæk"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Gervihnattar-SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Neyðarsímtöl eða SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Vinnusnið"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Þetta er ekki allra"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Fínstillingar kerfisviðmóts gera þér kleift að fínstilla og sérsníða notendaviðmót Android. Þessir tilraunaeiginleikar geta breyst, bilað eða horfið í síðari útgáfum. Gakktu því hægt um gleðinnar dyr."</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index b37eff908415..559e5290745a 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4811759950673118541">"UI sistema"</string>
+ <string name="app_label" msgid="4811759950673118541">"UI di sistema"</string>
<string name="battery_low_title" msgid="5319680173344341779">"Attivare il risparmio energetico?"</string>
<string name="battery_low_description" msgid="3282977755476423966">"Batteria rimanente: <xliff:g id="PERCENTAGE">%s</xliff:g>. Il risparmio energetico attiva il tema scuro, limita l\'attività in background e ritarda le notifiche."</string>
<string name="battery_low_intro" msgid="5148725009653088790">"Il risparmio energetico attiva il tema scuro, limita l\'attività in background e ritarda le notifiche."</string>
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usa il Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Dispositivo connesso"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Condivisione audio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Dispositivo salvato"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"disconnetti"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"attiva"</string>
@@ -390,7 +392,7 @@
<string name="performance" msgid="6552785217174378320">"Prestazioni"</string>
<string name="user_interface" msgid="3712869377953950887">"Interfaccia utente"</string>
<string name="thermal" msgid="6758074791325414831">"Termico"</string>
- <string name="custom" msgid="3337456985275158299">"Personalizzate"</string>
+ <string name="custom" msgid="3337456985275158299">"Personalizzata"</string>
<string name="custom_trace_settings_dialog_title" msgid="2608570500144830554">"Impostazioni di traccia personalizzate"</string>
<string name="restore_default" msgid="5259420807486239755">"Ripristina predefinite"</string>
<string name="quick_settings_onehanded_label" msgid="2416537930246274991">"Modalità a una mano"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellitare, connessione buona"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitare, connessione disponibile"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS satellitare"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chiamate di emergenza o SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profilo di lavoro"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Il divertimento riservato a pochi eletti"</string>
<string name="tuner_warning" msgid="1861736288458481650">"L\'Ottimizzatore UI di sistema mette a disposizione altri metodi per modificare e personalizzare l\'interfaccia utente di Android. Queste funzioni sperimentali potrebbero cambiare, interrompersi o scomparire nelle versioni successive. Procedi con cautela."</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index ecb840947cf9..907f8466b67c 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"‏שימוש ב-Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"מחובר"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"שיתוף אודיו"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"נשמר"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ניתוק"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"הפעלה"</string>
@@ -381,7 +383,7 @@
<string name="quick_settings_screen_record_start" msgid="1574725369331638985">"התחלה"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"עצירה"</string>
<string name="qs_record_issue_label" msgid="8166290137285529059">"תיעוד הבעיה"</string>
- <string name="qs_record_issue_start" msgid="2979831312582567056">"התחלה"</string>
+ <string name="qs_record_issue_start" msgid="2979831312582567056">"קדימה"</string>
<string name="qs_record_issue_stop" msgid="3531747965741982657">"עצירה"</string>
<string name="qs_record_issue_bug_report" msgid="8229031766918650079">"דיווח על באג"</string>
<string name="qs_record_issue_dropdown_header" msgid="5995983175678658329">"איזה חלק בחוויית השימוש שלך במכשיר הושפע?"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 98d320de2189..54ba7b5e7756 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth を使用"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"接続しました"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音声の共有"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"保存済み"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"接続を解除"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"有効化"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛生、接続状態良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛生、接続利用可能"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"衛星 SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"緊急通報または SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"仕事用プロファイル"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"一部の方のみお楽しみいただける限定公開ツール"</string>
<string name="tuner_warning" msgid="1861736288458481650">"システムUI調整ツールでは、Androidユーザーインターフェースの調整やカスタマイズを行えます。これらの試験運用機能は今後のリリースで変更となったり、中止となったり、削除されたりする可能性がありますのでご注意ください。"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index d85d7c1c26a7..bc0fa359ce0c 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-ის გამოყენება"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"დაკავშირებული"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"აუდიოს გაზიარება"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"შენახული"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"კავშირის გაწყვეტა"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"გააქტიურება"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"კარგი სატელიტური კავშირი"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ხელმისაწვდომია სატელიტური კავშირი"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"სატელიტური SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"გადაუდებელი ზარი ან SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"სამსახურის პროფილი"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ზოგისთვის გასართობია, მაგრამ არა ყველასთვის"</string>
<string name="tuner_warning" msgid="1861736288458481650">"სისტემის UI ტუნერი გაძლევთ დამატებით გზებს Android-ის სამომხმარებლო ინტერფეისის პარამეტრების დაყენებისთვის. ეს ექსპერიმენტული მახასიათებლები შეიძლება შეიცვალოს, შეწყდეს ან გაქრეს მომავალ ვერსიებში. სიფრთხილით გააგრძელეთ."</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 7a43b4b2395c..aa0678430940 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-ты пайдалану"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Қосылды"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Аудио бөлісу"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сақталды"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ажырату"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"іске қосу"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Жерсерік, байланыс жақсы."</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Жерсерік, байланыс бар."</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Құтқару қызметіне қоңырау шалу немесе SOS сигналын жіберу"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Жұмыс профилі"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Кейбіреулерге қызық, бірақ барлығына емес"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Жүйелік пайдаланушылық интерфейс тюнері Android пайдаланушылық интерфейсін реттеудің қосымша жолдарын береді. Бұл эксперименттік мүмкіндіктер болашақ шығарылымдарда өзгеруі, бұзылуы немесе жоғалуы мүмкін. Сақтықпен жалғастырыңыз."</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 2319623a80ef..fd64db57c79a 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ប្រើប៊្លូធូស"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"បានភ្ជាប់"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ការស្ដាប់សំឡេងរួមគ្នា"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"បាន​រក្សាទុក"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ផ្ដាច់"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"បើកដំណើរការ"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ផ្កាយរណប មានការតភ្ជាប់ល្អ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ផ្កាយរណប អាចតភ្ជាប់បាន"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ការប្រកាសអាសន្នតាមផ្កាយរណប"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ការហៅទៅលេខសង្គ្រោះបន្ទាន់ ឬ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"កម្រងព័ត៌មានការងារ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ល្អសម្រាប់អ្នកប្រើមួយចំនួន តែមិនសម្រាប់គ្រប់គ្នាទេ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"កម្មវិធីសម្រួល UI ប្រព័ន្ធផ្តល់ជូនអ្នកនូវមធ្យោបាយបន្ថែមទៀតដើម្បីកែសម្រួល និងប្តូរចំណុចប្រទាក់អ្នកប្រើ Android តាមបំណង។ លក្ខណៈពិសេសសាកល្បងនេះអាចនឹងផ្លាស់ប្តូរ បំបែក ឬបាត់បង់បន្ទាប់ពីការចេញផ្សាយនាពេលអនាគត។ សូមបន្តដោយប្រុងប្រយ័ត្ន។"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index aeb3b1ef0078..94979b056545 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ಬ್ಲೂಟೂತ್ ಬಳಸಿ"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ಕನೆಕ್ಟ್ ಆಗಿದೆ"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ಆಡಿಯೋ ಹಂಚಿಕೊಳ್ಳುವಿಕೆ"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ಸೇವ್ ಮಾಡಲಾಗಿದೆ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ಡಿಸ್‌ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ಸ್ಯಾಟಲೈಟ್‌, ಕನೆಕ್ಷನ್ ಉತ್ತಮವಾಗಿದೆ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ಸ್ಯಾಟಲೈಟ್, ಕನೆಕ್ಷನ್ ಲಭ್ಯವಿದೆ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ಸ್ಯಾಟಲೈಟ್ SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ತುರ್ತು ಕರೆಗಳು ಅಥವಾ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ಕೆಲಸದ ಪ್ರೊಫೈಲ್"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ಕೆಲವರಿಗೆ ಮೋಜು ಆಗಿದೆ ಎಲ್ಲರಿಗೆ ಇಲ್ಲ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ಸಿಸ್ಟಂ UI ಟ್ಯೂನರ್ ನಿಮಗೆ Android ಬಳಕೆದಾರ ಅಂತರಸಂಪರ್ಕವನ್ನು ಸರಿಪಡಿಸಲು ಮತ್ತು ಕಸ್ಟಮೈಸ್ ಮಾಡಲು ಹೆಚ್ಚುವರಿ ಮಾರ್ಗಗಳನ್ನು ನೀಡುತ್ತದೆ. ಈ ಪ್ರಾಯೋಗಿಕ ವೈಶಿಷ್ಟ್ಯಗಳು ಭವಿಷ್ಯದ ಬಿಡುಗಡೆಗಳಲ್ಲಿ ಬದಲಾಗಬಹುದು, ವಿರಾಮವಾಗಬಹುದು ಅಥವಾ ಕಾಣಿಸಿಕೊಳ್ಳದಿರಬಹುದು. ಎಚ್ಚರಿಕೆಯಿಂದ ಮುಂದುವರಿಯಿರಿ."</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 277582c75200..e316ffdb14a4 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"블루투스 사용"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"연결됨"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"오디오 공유"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"저장됨"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"연결 해제"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"실행"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"위성, 연결 상태 양호"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"위성, 연결 가능"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"위성 긴급 SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"긴급 전화 또는 SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"직장 프로필"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"마음에 들지 않을 수도 있음"</string>
<string name="tuner_warning" msgid="1861736288458481650">"시스템 UI 튜너를 사용하면 Android 사용자 인터페이스를 변경 및 맞춤설정할 수 있습니다. 이러한 실험실 기능은 향후 출시 버전에서는 변경되거나 다운되거나 사라질 수 있습니다. 신중하게 진행하시기 바랍니다."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 4680236c39fb..ec07794667c0 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -110,7 +110,7 @@
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"Экранды жаздырасызбы?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"Бир колдонмону жаздыруу"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"Бүтүндөй экранды жаздыруу"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Бүт экранды жаздырганда экранда көрүнүп турган нерселердин баары жаздырылат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"Бүтүндөй экранды жаздырганда, андагы нерселердин баары видеого түшүп калат. Андыктан этият болуп, сырсөздөр, төлөм ыкмалары, билдирүүлөр, сүрөттөр, аудио жана видео материалдар сыяктуу купуя нерселерди көрсөтүп албаңыз."</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"Колдонмону жаздырганда ал колдонмодо көрсөтүлүп же ойнотулуп жаткан нерселер жаздырылат. Андыктан сырсөздөрдү, төлөмдүн чоо-жайын, билдирүүлөрдү, сүрөттөрдү, аудио жана видеону көрсөтүп албаңыз."</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"Экранды жаздыруу"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"Жаздыруу үчүн колдонмо тандоо"</string>
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Иштетүү"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Туташты"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Чогуу угуу"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сакталды"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ажыратуу"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"иштетүү"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спутник, байланыш жакшы"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Спутник, байланыш бар"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Спутник SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Шашылыш чалуулар же SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Жумуш профили"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Баарына эле жага бербейт"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner Android колдонуучу интерфейсин жөнгө салып жана ыңгайлаштыруунун кошумча ыкмаларын сунуштайт. Бул сынамык функциялар кийинки чыгарылыштарда өзгөрүлүп, бузулуп же жоголуп кетиши мүмкүн. Абайлап колдонуңуз."</string>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index edb8fa338d7a..5ac2a6f2df34 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ໃຊ້ Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ເຊື່ອມຕໍ່ແລ້ວ"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ການແບ່ງປັນສຽງ"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ບັນທຶກແລ້ວ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ຕັດການເຊື່ອມຕໍ່"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ເປີດນຳໃຊ້"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ດາວທຽມ, ການເຊື່ອມຕໍ່ດີ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ດາວທຽມ, ການເຊື່ອມຕໍ່ທີ່ພ້ອມນຳໃຊ້"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS ດາວທຽມ"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ໂທສຸກເສີນ ຫຼື SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ມ່ວນຊື່ນສຳລັບບາງຄົນ ແຕ່ບໍ່ແມ່ນສຳລັບທຸກຄົນ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner ໃຫ້ທ່ານມີວິທີພິເສດຕື່ມອີກໃນການປັບປ່ຽນ ແລະຕົບແຕ່ງສ່ວນຕໍ່ປະສານຜູ້ໃຊ້ຂອງ Android. ຄຸນສົມບັດທົດລອງໃຊ້ເຫຼົ່ານີ້ອາດຈະປ່ຽນແປງ, ຢຸດເຊົາ ຫຼືຫາຍໄປໃນການວາງຈຳໜ່າຍໃນອະນາຄົດ. ຈົ່ງດຳເນີນຕໍ່ດ້ວຍຄວາມລະມັດລະວັງ."</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index a9a0e73c4322..051650477e38 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"„Bluetooth“ naudojimas"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Prisijungta"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Garso įrašų bendrinimas"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Išsaugota"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"atjungti"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"suaktyvinti"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Palydovas, geras ryšys"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Palydovas, pasiekiamas ryšys"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Prisijungimas prie palydovo kritiniu atveju"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Skambučiai pagalbos numeriu arba pagalbos iškvietimas kritiniu atveju"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Darbo profilis"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Smagu, bet ne visada"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistemos naudotojo sąsajos derinimo priemonė suteikia papildomų galimybių pagerinti ir tinkinti „Android“ naudotojo sąsają. Šios eksperimentinės funkcijos gali pasikeisti, nutrūkti ar išnykti iš būsimų laidų. Tęskite atsargiai."</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index d1e97a65e159..baf03e23af48 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Izmantot Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Savienojums izveidots"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio kopīgošana"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saglabāta"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"atvienot"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivizēt"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelīts, labs savienojums"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelīts, ir pieejams savienojums"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelīta SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Ārkārtas izsaukumi vai ārkārtas zvani"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Darba profils"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Jautri dažiem, bet ne visiem"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistēmas saskarnes regulators sniedz papildu veidus, kā mainīt un pielāgot Android lietotāja saskarni. Nākamajās versijās šīs eksperimentālās funkcijas var tikt mainītas, bojātas vai to darbība var tikt pārtraukta. Turpinot esiet uzmanīgs."</string>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 7691ae6181a2..24bdae3e9670 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Користи Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Поврзано"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Споделување аудио"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Зачувано"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекини врска"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активирај"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Добра сателитска врска"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Достапна е сателитска врска"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Сателитски SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Итни повици или SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Работен профил"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забава за некои, но не за сите"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Адаптерот на УИ на системот ви дава дополнителни начини за дотерување и приспособување на корисничкиот интерфејс на Android. Овие експериментални функции можеби ќе се изменат, расипат или ќе исчезнат во следните изданија. Продолжете со претпазливост."</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 8c0378a6bd6b..32f840ea6c12 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth ഉപയോഗിക്കുക"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"കണക്‌റ്റ് ചെയ്‌തു"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ഓഡിയോ പങ്കിടൽ"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"സംരക്ഷിച്ചു"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"വിച്ഛേദിക്കുക"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"സജീവമാക്കുക"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"സാറ്റലൈറ്റ്, മികച്ച കണക്ഷൻ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"സാറ്റലൈറ്റ്, കണക്ഷൻ ലഭ്യമാണ്"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"സാറ്റലൈറ്റ് SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"എമർജൻസി കോൾ അല്ലെങ്കിൽ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ചിലർക്ക് വിനോദം, എന്നാൽ എല്ലാവർക്കുമില്ല"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Android ഉപയോക്തൃ ഇന്റർഫേസ് ആവശ്യമുള്ള രീതിയിൽ മാറ്റുന്നതിനും ഇഷ്ടാനുസൃതമാക്കുന്നതിനും സിസ്റ്റം UI ട്യൂണർ നിങ്ങൾക്ക് അധിക വഴികൾ നൽകുന്നു. ഭാവി റിലീസുകളിൽ ഈ പരീക്ഷണാത്മക ഫീച്ചറുകൾ മാറ്റുകയോ നിർത്തുകയോ അപ്രത്യക്ഷമാവുകയോ ചെയ്തേക്കാം. ശ്രദ്ധയോടെ മുന്നോട്ടുപോകുക."</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index bfd48a45a629..d2295898671e 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth-г ашиглах"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Холбогдсон"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Аудио хуваалцах"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Хадгалсан"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"салгах"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"идэвхжүүлэх"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Хиймэл дагуул, холболт сайн байна"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Хиймэл дагуул, холболт боломжтой"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Хиймэл дагуул SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Яаралтай дуудлага эсвэл SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Ажлын профайл"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Зарим хүнд хөгжилтэй байж болох ч бүх хүнд тийм биш"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Системийн UI Tохируулагч нь Android хэрэглэгчийн интерфэйсийг тааруулах, өөрчлөх нэмэлт аргыг зааж өгөх болно. Эдгээр туршилтын тохиргоо нь цаашид өөрчлөгдөх, эвдрэх, алга болох магадлалтай. Үйлдлийг болгоомжтой хийнэ үү."</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index d124ce366bb9..5ec388d62247 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्‍लूटूथ वापरा"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट केले"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ऑडिओ शेअरिंग"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेव्ह केले"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिस्कनेक्ट करा"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ॲक्टिव्हेट करा"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"सॅटेलाइट, चांगले कनेक्शन"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"सॅटेलाइट, कनेक्शन उपलब्ध"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"सॅटेलाइट SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"आणीबाणी कॉल किंवा SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाईल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"सर्वांसाठी नाही तर काहींसाठी मजेदार असू शकते"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनर आपल्‍याला Android यूझर इंटरफेस ट्विक आणि कस्टमाइझ करण्‍याचे अनेक प्रकार देते. ही प्रयोगात्मक वैशिष्‍ट्ये बदलू शकतात, खंडित होऊ शकतात किंवा भविष्‍यातील रिलीज मध्‍ये कदाचित दिसणार नाहीत. सावधगिरी बाळगून पुढे सुरू ठेवा."</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 8385682e6939..9a9455acfc3a 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Gunakan Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Disambungkan"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Perkongsian Audio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Disimpan"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"putuskan sambungan"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktifkan"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, sambungan yang baik"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, sambungan tersedia"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via Satelit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Panggilan kecemasan atau SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil kerja"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Menarik untuk sesetengah orang tetapi bukan untuk semua"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Penala UI Sistem memberi anda cara tambahan untuk mengolah dan menyesuaikan antara muka Android. Ciri eksperimen ini boleh berubah, rosak atau hilang dalam keluaran masa hadapan. Teruskan dengan berhati-hati."</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 60c74c1ca148..622b1d50f7f4 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ဘလူးတုသ်သုံးရန်"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ချိတ်ဆက်ထားသည်"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"အော်ဒီယို မျှဝေခြင်း"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"သိမ်းထားသည်"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ချိတ်ဆက်မှုဖြုတ်ရန်"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"စသုံးရန်"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု ကောင်းသည်"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ဂြိုဟ်တု၊ ချိတ်ဆက်မှု ရနိုင်သည်"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"အရေးပေါ်ဖုန်းခေါ်ခြင်း (သို့) SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"အလုပ် ပရိုဖိုင်"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"အချို့သူများ အတွက် ပျော်စရာ ဖြစ်ပေမဲ့ အားလုံး အတွက် မဟုတ်ပါ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"စနစ် UI Tuner က သင့်အတွက် Android အသုံးပြုသူ အင်တာဖေ့စ်ကို ပြောင်းရန်နှင့် စိတ်ကြိုက်ပြုလုပ်ရန် နည်းလမ်း အပိုများကို သင့်အတွက် စီစဉ်ပေးသည်။ အနာဂတ်ဗားရှင်းများတွင် ဤစမ်းသပ်အင်္ဂါရပ်များမှာ ပြောင်းလဲ၊ ပျက်စီး သို့မဟုတ် ပျောက်ကွယ်သွားနိုင်သည်။ သတိဖြင့် ရှေ့ဆက်ပါ။"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 72ccd2c4137f..119184439c7f 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bruk Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Tilkoblet"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Lyddeling"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Lagret"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"koble fra"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiver"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellitt – god tilkobling"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellitt – tilkobling tilgjengelig"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-alarm via satellitt"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Nødanrop eller SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Work-profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Gøy for noen – ikke for alle"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Med System UI Tuner har du flere måter å justere og tilpasse Android-brukergrensesnittet på. Disse eksperimentelle funksjonene kan endres, avbrytes eller fjernes i fremtidige utgivelser. Fortsett med forbehold."</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index d6806456e54a..610a44911e1a 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ब्लुटुथ प्रयोग गर्नुहोस्"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"कनेक्ट गरिएको छ"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"अडियो सेयरिङ"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"सेभ गरिएको छ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"डिस्कनेक्ट गर्नुहोस्"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"एक्टिभेट गर्नुहोस्"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"स्याटलाइट, राम्रो कनेक्सन"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"स्याटलाइट, कनेक्सन उपलब्ध छ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"स्याटलाइट SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"आपत्कालीन कल वा SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"कार्य प्रोफाइल"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"केहीका लागि रमाइलो हुन्छ तर सबैका लागि होइन"</string>
<string name="tuner_warning" msgid="1861736288458481650">"सिस्टम UI ट्युनरले तपाईँलाई Android प्रयोगकर्ता इन्टरफेस कस्टम गर्न र ट्विक गर्न थप तरिकाहरू प्रदान गर्छ। यी प्रयोगात्मक सुविधाहरू भावी विमोचनमा परिवर्तन हुन, बिग्रिन वा हराउन सक्ने छन्। सावधानीपूर्वक अगाडि बढ्नुहोस्।"</string>
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 21f1cfbe4c9e..c1eff5f629b3 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -16,7 +16,11 @@
NOTE: You might also want to edit: core/res/res/values-night/*.xml
-->
-<resources>
+<resources xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
+ <!-- The dark background color behind the shade -->
+ <color name="shade_scrim_background_dark">@androidprv:color/system_under_surface_dark</color>
+
<!-- The color of the legacy notifications with customs backgrounds (gingerbread and lollipop.)
It's fine to override this color since at that point the shade was dark. -->
<color name="notification_legacy_background_color">@color/GM2_grey_900</color>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 6a675b8890c2..404d768c246a 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth gebruiken"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Verbonden"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio delen"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Opgeslagen"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"loskoppelen"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activeren"</string>
@@ -629,7 +631,7 @@
<string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Instellingen"</string>
<string name="volume_panel_captioning_title" msgid="5984936949147684357">"Live ondertiteling"</string>
<string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Volume verlaagd naar een veiliger niveau"</string>
- <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Het hoofdtelefoonvolume is langer dan de aanbevolen tijd hoog geweest"</string>
+ <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Het koptelefoonvolume is langer dan de aanbevolen tijd hoog geweest"</string>
<string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Het hoofdtelefoonvolume overschrijdt de veiligheidslimiet voor deze week"</string>
<string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Blijven luisteren"</string>
<string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Volume omlaag"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelliet, goede verbinding"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelliet, verbinding beschikbaar"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satelliet"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Noodoproepen of SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Werkprofiel"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Leuk voor sommige gebruikers, maar niet voor iedereen"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Met Systeem-UI-tuner beschikt u over extra manieren om de Android-gebruikersinterface aan te passen. Deze experimentele functies kunnen veranderen, vastlopen of verdwijnen in toekomstige releases. Ga voorzichtig verder."</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 6e6364302546..5b9d747c832c 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ବ୍ଲୁଟୁଥ ବ୍ୟବହାର କରନ୍ତୁ"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"କନେକ୍ଟ କରାଯାଇଛି"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ଅଡିଓ ସେୟାରିଂ"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ସେଭ କରାଯାଇଛି"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ଡିସକନେକ୍ଟ କରନ୍ତୁ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ଚାଲୁ କରନ୍ତୁ"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ସାଟେଲାଇଟ, ଭଲ କନେକ୍ସନ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ସାଟେଲାଇଟ, କନେକ୍ସନ ଉପଲବ୍ଧ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ସେଟେଲାଇଟ SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ଜରୁରୀକାଳୀନ କଲ କିମ୍ବା SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"କେତେକଙ୍କ ପାଇଁ ମଜାଦାର, କିନ୍ତୁ ସମସ୍ତଙ୍କ ପାଇଁ ନୁହେଁ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Android ୟୁଜର୍‍ ଇଣ୍ଟରଫେସ୍‍ ବଦଳାଇବାକୁ ତଥା ନିଜ ପସନ୍ଦ ଅନୁଯାୟୀ କରିବାକୁ ସିଷ୍ଟମ୍‍ UI ଟ୍ୟୁନର୍‍ ଆପଣଙ୍କୁ ଅତିରିକ୍ତ ଉପାୟ ପ୍ରଦାନ କରେ। ଏହି ପରୀକ୍ଷାମୂଳକ ସୁବିଧାମାନ ବଦଳିପାରେ, ଭାଙ୍ଗିପାରେ କିମ୍ବା ଭବିଷ୍ୟତର ରିଲିଜ୍‌ଗୁଡ଼ିକରେ ନଦେଖାଯାଇପାରେ। ସତର୍କତାର ସହ ଆଗକୁ ବଢ଼ନ୍ତୁ।"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index cd7790fd4be1..c9a45ba88b58 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -110,7 +110,7 @@
<string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"ਕੀ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨਾ ਹੈ?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"ਇੱਕ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰੋ"</string>
- <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"ਜਦੋਂ ਤੁਸੀਂ ਆਪਣੀ ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਾਈ ਜਾ ਰਹੀ ਹਰ ਚੀਜ਼ ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
+ <string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"ਜਦੋਂ ਤੁਸੀਂ ਆਪਣੀ ਪੂਰੀ ਸਕ੍ਰੀਨ ਨੂੰ ਰਿਕਾਰਡ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹੋ, ਤਾਂ ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਖਾਈ ਜਾ ਰਹੀ ਹਰ ਚੀਜ਼ ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਨਾਲ ਹੀ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
<string name="screenrecord_permission_dialog_warning_single_app" msgid="3738199712880063924">"ਜਦੋਂ ਤੁਸੀਂ ਕਿਸੇ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰ ਰਹੇ ਹੁੰਦੇ ਹੋ, ਤਾਂ ਉਸ ਐਪ ਵਿੱਚ ਦਿਖਾਈ ਜਾਂ ਚਲਾਈ ਜਾ ਰਹੀ ਹਰ ਚੀਜ਼ ਨੂੰ ਰਿਕਾਰਡ ਕੀਤਾ ਜਾਂਦਾ ਹੈ। ਇਸ ਲਈ ਪਾਸਵਰਡਾਂ, ਭੁਗਤਾਨ ਵੇਰਵਿਆਂ, ਸੁਨੇਹਿਆਂ, ਫ਼ੋਟੋਆਂ ਅਤੇ ਆਡੀਓ ਅਤੇ ਵੀਡੀਓ ਵਰਗੀਆਂ ਚੀਜ਼ਾਂ ਵਾਸਤੇ ਸਾਵਧਾਨ ਰਹੋ।"</string>
<string name="screenrecord_permission_dialog_continue_entire_screen" msgid="5557974446773486600">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡ ਕਰੋ"</string>
<string name="screenrecord_app_selector_title" msgid="3854492366333954736">"ਰਿਕਾਰਡ ਕਰਨ ਲਈ ਐਪ ਚੁਣੋ"</string>
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ਬਲੂਟੁੱਥ ਵਰਤੋ"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"ਕਨੈਕਟ ਹੈ"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ਆਡੀਓ ਸਾਂਝਾਕਰਨ"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"ਰੱਖਿਅਤ ਕੀਤਾ ਗਿਆ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ਕਿਰਿਆਸ਼ੀਲ ਕਰੋ"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਵਧੀਆ ਹੈ"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ਸੈਟੇਲਾਈਟ, ਕਨੈਕਸ਼ਨ ਉਪਲਬਧ ਹੈ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ਸੈਟੇਲਾਈਟ SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ਐਮਰਜੈਂਸੀ ਕਾਲਾਂ ਜਾਂ ਸਹਾਇਤਾ"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"ਕੁਝ ਵਾਸਤੇ ਤਾਂ ਮਜ਼ੇਦਾਰ ਹੈ ਲੇਕਿਨ ਸਾਰਿਆਂ ਵਾਸਤੇ ਨਹੀਂ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ਸਿਸਟਮ UI ਟਿਊਨਰ ਤੁਹਾਨੂੰ Android ਵਰਤੋਂਕਾਰ ਇੰਟਰਫ਼ੇਸ ਤਬਦੀਲ ਕਰਨ ਅਤੇ ਵਿਉਂਤਬੱਧ ਕਰਨ ਲਈ ਵਾਧੂ ਤਰੀਕੇ ਦਿੰਦਾ ਹੈ। ਇਹ ਪ੍ਰਯੋਗਾਤਮਿਕ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਭਵਿੱਖ ਦੀ ਰੀਲੀਜ਼ ਵਿੱਚ ਬਦਲ ਸਕਦੀਆਂ ਹਨ, ਟੁੱਟ ਸਕਦੀਆਂ ਹਨ, ਜਾਂ ਅਲੋਪ ਹੋ ਸਕਦੀਆਂ ਹਨ। ਸਾਵਧਾਨੀ ਨਾਲ ਅੱਗੇ ਵੱਧੋ।"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index cf881721bfe0..f4674097863d 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -19,7 +19,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="4811759950673118541">"UI systemu"</string>
+ <string name="app_label" msgid="4811759950673118541">"Interfejs systemu"</string>
<string name="battery_low_title" msgid="5319680173344341779">"Włączyć Oszczędzanie baterii?"</string>
<string name="battery_low_description" msgid="3282977755476423966">"Masz już tylko <xliff:g id="PERCENTAGE">%s</xliff:g> baterii. Oszczędzanie baterii uruchamia ciemny motyw, ogranicza aktywność w tle i opóźnia powiadomienia."</string>
<string name="battery_low_intro" msgid="5148725009653088790">"Oszczędzanie baterii uruchamia ciemny motyw, ogranicza aktywność w tle i opóźnia powiadomienia."</string>
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Używaj Bluetootha"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Połączone"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Udostępnianie dźwięku"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Zapisane"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"rozłącz"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktywuj"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelita – połączenie dobre"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelita – połączenie dostępne"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satelitarne połączenie alarmowe"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Połączenia alarmowe lub SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil służbowy"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Dobra zabawa, ale nie dla każdego"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Kalibrator System UI udostępnia dodatkowe sposoby dostrajania i dostosowywania interfejsu Androida. Te eksperymentalne funkcje mogą się zmienić, popsuć lub zniknąć w przyszłych wersjach. Zachowaj ostrożność."</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index c2c40db52841..154fc3db3bbf 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartilhamento de áudio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvo"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, conexão boa"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satélite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emergência ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index c52354fb50c6..d96c540c46d7 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ligado"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Partilha de áudio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Guardado"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desassociar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, boa ligação"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, ligação disponível"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satélite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emergência ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O Sintonizador da interface do sistema disponibiliza-lhe formas adicionais ajustar e personalizar a interface do utilizador do Android. Estas funcionalidades experimentais podem ser alteradas, deixar de funcionar ou desaparecer em versões futuras. Prossiga com cuidado."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index c2c40db52841..154fc3db3bbf 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Usar Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectado"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Compartilhamento de áudio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvo"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"desconectar"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"ativar"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satélite, conexão boa"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satélite, conexão disponível"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS via satélite"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Chamadas de emergência ou SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Perfil de trabalho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diversão para alguns, mas não para todos"</string>
<string name="tuner_warning" msgid="1861736288458481650">"O sintonizador System UI fornece maneiras adicionais de ajustar e personalizar a interface do usuário do Android. Esses recursos experimentais podem mudar, falhar ou desaparecer nas versões futuras. Prossiga com cuidado."</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 1f7b7164d4b2..5e1eee355c6f 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Folosește Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Conectat"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Permiterea accesului la audio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Salvat"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"deconectează"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"activează"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, conexiune bună"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, conexiune disponibilă"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS prin satelit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Apeluri de urgență sau SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profil de serviciu"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Distractiv pentru unii, dar nu pentru toată lumea"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner oferă modalități suplimentare de a ajusta și a personaliza interfața de utilizare Android. Aceste funcții experimentale pot să se schimbe, să se blocheze sau să dispară din versiunile viitoare. Continuă cu prudență."</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index 0b545ce46eed..e938ca0fa024 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Использовать"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Подключено"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Отправка аудио"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сохранено"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"отключить"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активировать"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Спутниковая связь, хорошее качество соединения"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступно соединение по спутниковой связи"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Спутниковый SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Экстренные вызовы или спутниковый SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Рабочий профиль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Внимание!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner позволяет настраивать интерфейс устройства Android по вашему вкусу. В будущем эта экспериментальная функция может измениться, перестать работать или исчезнуть."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index b34b8a38b358..7b2b2be9034c 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"බ්ලූටූත් භාවිතා කරන්න"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"සම්බන්ධිතයි"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ශ්‍රව්‍ය බෙදා ගැනීම"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"සුරැකිණි"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"විසන්ධි කරන්න"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"සක්‍රිය කරන්න"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"චන්ද්‍රිකාව, හොඳ සම්බන්ධතාවයක්"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"චන්ද්‍රිකාව, සම්බන්ධතාවය තිබේ"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"චන්ද්‍රිකා SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"හදිසි ඇමතුම් හෝ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"කාර්යාල පැතිකඩ"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"සමහරක් දේවල් වලට විනෝදයි, නමුත් සියල්ලටම නොවේ"</string>
<string name="tuner_warning" msgid="1861736288458481650">"පද්ධති UI සුසරකය ඔබට Android පරිශීලක අතුරු මුහුණත වෙනස් කිරීමට හෝ අභිරුචිකරණය කිරීමට අමතර ක්‍රම ලබා දේ. මෙම පර්යේෂණාත්මක අංග ඉදිරි නිකුත් වීම් වල වෙනස් වීමට, වැඩ නොකිරීමට, හෝ නැතිවීමට හැක. ප්‍රවේශමෙන් ඉදිරියට යන්න."</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index b1983b87a0b4..877e87bf3b6d 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Používať Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Pripojené"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Zdieľanie zvuku"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Uložené"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"odpojiť"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivovať"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobrá kvalita pripojenia"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, pripojenie je k dispozícii"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Pomoc cez satelit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Tiesňové volania alebo pomoc v tiesni"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Pracovný profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Pri používaní tuneru postupujte opatrne"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Tuner používateľského rozhrania systému poskytujte ďalšie spôsoby ladenia a prispôsobenia používateľského rozhrania Android. Tieto experimentálne funkcie sa môžu v budúcich verziách zmeniť, ich poskytovanie môže byť prerušené alebo môžu byť odstránené. Pokračujte opatrne."</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index a3b042e0959f..22c5293c8380 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Uporabi Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Povezano"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Deljenje zvoka"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Shranjeno"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"prekinitev povezave"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktiviranje"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satelit, dobra povezava"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satelit, povezava je na voljo"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS prek satelita"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Klici v sili ali SOS prek satelita"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Delovni profil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Zabavno za nekatere, a ne za vse"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Uglaševalnik uporabniškega vmesnika sistema vam omogoča dodatne načine za spreminjanje in prilagajanje uporabniškega vmesnika Android. Te poskusne funkcije lahko v prihodnjih izdajah kadar koli izginejo, se spremenijo ali pokvarijo. Bodite previdni."</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 4cba52795ff6..a864df950afe 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Përdor Bluetooth-in"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Lidhur"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ndarja e audios"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Ruajtur"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"shkëput"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivizo"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Sateliti. Lidhje e mirë"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sateliti. Ofrohet lidhje"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS satelitor"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Telefonatat e urgjencës ose SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profili i punës"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Argëtim për disa, por jo për të gjithë!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sintonizuesi i Sistemit të Ndërfaqes së Përdoruesit të jep mënyra shtesë për të tërhequr dhe personalizuar ndërfaqen Android të përdoruesit. Këto funksione eksperimentale mund të ndryshojnë, prishen ose zhduken në versionet e ardhshme. Vazhdo me kujdes."</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 26c135b8d213..91fdf2aaf9f9 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Користи Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Повезано"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Дељење звука"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Сачувано"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"прекините везу"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активирајте"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Сателит, веза је добра"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Сателит, веза је доступна"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Хитна помоћ преко сателита"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Хитни позиви или хитна помоћ"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Пословни профил"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Забава за неке, али не за све"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Тјунер за кориснички интерфејс система вам пружа додатне начине за подешавање и прилагођавање Android корисничког интерфејса. Ове експерименталне функције могу да се промене, откажу или нестану у будућим издањима. Будите опрезни."</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 56cc4427bf17..dfd65bb60e34 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Använd Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ansluten"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ljuddelning"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Sparad"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"koppla från"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"aktivera"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellit, bra anslutning"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellit, anslutning tillgänglig"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS-larm via satellit"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Nödsamtal eller SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Jobbprofil"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kul för vissa, inte för alla"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Du kan använda inställningarna för systemgränssnitt för att justera användargränssnittet i Android. Dessa experimentfunktioner kan när som helst ändras, sluta fungera eller försvinna. Använd med försiktighet."</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index db237b501a53..809d2c4f02f9 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -124,7 +124,7 @@
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Inarekodi skrini na sauti"</string>
<string name="screenrecord_taps_label" msgid="1595690528298857649">"Onyesha sehemu za kugusa kwenye skrini"</string>
<string name="screenrecord_stop_label" msgid="72699670052087989">"Acha"</string>
- <string name="screenrecord_share_label" msgid="5025590804030086930">"Shiriki"</string>
+ <string name="screenrecord_share_label" msgid="5025590804030086930">"Tuma"</string>
<string name="screenrecord_save_title" msgid="1886652605520893850">"Imehifadhi rekodi ya skrini"</string>
<string name="screenrecord_save_text" msgid="3008973099800840163">"Gusa ili uangalie"</string>
<string name="screenrecord_save_error" msgid="5862648532560118815">"Hitilafu imetokea wakati wa kuhifadhi rekodi ya skrini"</string>
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Tumia Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Imeunganishwa"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Kusikiliza Pamoja"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Imehifadhiwa"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ondoa"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"anza kutumia"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Setilaiti, muunganisho thabiti"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Setilaiti, muunganisho unapatikana"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Msaada kupitia Setilaiti"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Simu za dharura"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Wasifu wa kazini"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kinafurahisha kwa baadhi ya watu lakini si wote"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Kirekebishi cha kiolesura cha mfumo kinakupa njia zaidi za kugeuza na kubadilisha kiolesura cha Android ili kikufae. Vipengele hivi vya majaribio vinaweza kubadilika, kuharibika au kupotea katika matoleo ya siku zijazo. Endelea kwa uangalifu."</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index e617e88d8f1d..ee8e11f430d3 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"புளூடூத்தைப் பயன்படுத்துதல்"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"இணைக்கப்பட்டது"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ஆடியோ பகிர்வு"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"சேமிக்கப்பட்டது"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"இணைப்பு நீக்கும்"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"செயல்படுத்தும்"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"சாட்டிலைட், நிலையான இணைப்பு"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"சாட்டிலைட், இணைப்பு கிடைக்கிறது"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"சாட்டிலைட் SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"அவசர அழைப்புகள் அல்லது SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"பணிக் கணக்கு"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"சில வேடிக்கையாக இருந்தாலும் கவனம் தேவை"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner, Android பயனர் இடைமுகத்தை மாற்றவும் தனிப்பயனாக்கவும் கூடுதல் வழிகளை வழங்குகிறது. இந்தப் பரிசோதனைக்குரிய அம்சங்கள் எதிர்கால வெளியீடுகளில் மாற்றப்படலாம், இடைநிறுத்தப்படலாம் அல்லது தோன்றாமல் போகலாம். கவனத்துடன் தொடரவும்."</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index b45e82b0e704..d09f3ec091bf 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"బ్లూటూత్ వాడండి"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"కనెక్ట్ అయింది"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"ఆడియో షేరింగ్"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"సేవ్ అయ్యింది"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"డిస్‌కనెక్ట్ చేయండి"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"యాక్టివేట్ చేయండి"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"శాటిలైట్, కనెక్షన్ బాగుంది"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"శాటిలైట్, కనెక్షన్ అందుబాటులో ఉంది"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"ఎమర్జెన్సీ శాటిలైట్ సహాయం"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"ఎమర్జెన్సీ కాల్స్ లేదా SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"ఆఫీస్ ప్రొఫైల్‌"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"కొందరికి సరదాగా ఉంటుంది కానీ అందరికీ అలాగే ఉండదు"</string>
<string name="tuner_warning" msgid="1861736288458481650">"సిస్టమ్ UI ట్యూనర్ Android వినియోగదారు ఇంటర్‌ఫేస్‌ను మెరుగుపరచడానికి మరియు అనుకూలంగా మార్చడానికి మీకు మరిన్ని మార్గాలను అందిస్తుంది. ఈ ప్రయోగాత్మక లక్షణాలు భవిష్యత్తు విడుదలల్లో మార్పుకు లోనవ్వచ్చు, తాత్కాలికంగా లేదా పూర్తిగా నిలిపివేయవచ్చు. జాగ్రత్తగా కొనసాగండి."</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 252fc05f8b6d..ddea72f4cf90 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"ใช้บลูทูธ"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"เชื่อมต่อแล้ว"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"การแชร์เสียง"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"บันทึกแล้ว"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ยกเลิกการเชื่อมต่อ"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"เปิดใช้งาน"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"ดาวเทียม, การเชื่อมต่อดี"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"ดาวเทียม, การเชื่อมต่อที่พร้อมใช้งาน"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"SOS ดาวเทียม"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"การโทรฉุกเฉินหรือ SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"โปรไฟล์งาน"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"เพลิดเพลินกับบางส่วนแต่ไม่ใช่ทั้งหมด"</string>
<string name="tuner_warning" msgid="1861736288458481650">"ตัวรับสัญญาณ UI ระบบช่วยให้คุณมีวิธีพิเศษในการปรับแต่งและกำหนดค่าส่วนติดต่อผู้ใช้ Android ฟีเจอร์รุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 04f52ea5f659..7247757eafab 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Gumamit ng Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Nakakonekta"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Pag-share ng Audio"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Na-save"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"idiskonekta"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"i-activate"</string>
@@ -629,7 +631,7 @@
<string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Mga Setting"</string>
<string name="volume_panel_captioning_title" msgid="5984936949147684357">"Instant Caption"</string>
<string name="csd_lowered_title" product="default" msgid="2464112924151691129">"Ibinaba sa mas ligtas na level ang volume"</string>
- <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Naging malakas ang volume ng headphones nang mas matagal sa inirerekomenda"</string>
+ <string name="csd_system_lowered_text" product="default" msgid="1250251883692996888">"Malakas ang volume ng headphones nang mas matagal sa inirerekomenda"</string>
<string name="csd_500_system_lowered_text" product="default" msgid="7414943302186884124">"Lampas na sa ligtas na limitasyon para sa linggong ito ang volume ng headphone"</string>
<string name="csd_button_keep_listening" product="default" msgid="4093794049149286784">"Magpatuloy sa pakikinig"</string>
<string name="csd_button_lower_volume" product="default" msgid="5347210412376264579">"Hinaan"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Satellite, malakas ang koneksyon"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Satellite, may koneksyon"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Satellite SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Mga emergency na tawag o SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Profile sa trabaho"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Masaya para sa ilan ngunit hindi para sa lahat"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Nagbibigay sa iyo ang Tuner ng System UI ng mga karagdagang paraan upang baguhin at i-customize ang user interface ng Android. Ang mga pang-eksperimentong feature na ito ay maaaring magbago, masira o mawala sa mga pagpapalabas sa hinaharap. Magpatuloy nang may pag-iingat."</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 19c9e0c50987..067d2078c453 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth\'u kullan"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Bağlandı"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ses Paylaşımı"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Kaydedildi"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"bağlantıyı kes"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"etkinleştir"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Uydu, bağlantı güçlü"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Uydu, bağlantı mevcut"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Acil Uydu Bağlantısı"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Acil durum aramaları veya acil yardım"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"İş profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Bazıları için eğlenceliyken diğerleri için olmayabilir"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Sistem Kullanıcı Arayüzü Ayarlayıcı, Android kullanıcı arayüzünde değişiklikler yapmanız ve arayüzü özelleştirmeniz için ekstra yollar sağlar. Bu deneysel özellikler değişebilir, bozulabilir veya gelecekteki sürümlerde yer almayabilir. Dikkatli bir şekilde devam edin."</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 8af4120d09d9..7ffb958979a6 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Увімкнути Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Підключено"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Надсилання аудіо"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Збережено"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"від’єднати"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"активувати"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Хороше з’єднання із супутником"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Доступне з’єднання із супутником"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Супутниковий сигнал SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Екстрені виклики або сигнал SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Робочий профіль"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Це цікаво, але будьте обачні"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner пропонує нові способи налаштувати та персоналізувати інтерфейс користувача Android. Ці експериментальні функції можуть змінюватися, не працювати чи зникати в майбутніх версіях. Будьте обачні."</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index dd275154d448..b2d4a11a4266 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"بلوٹوتھ استعمال کریں"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"منسلک ہے"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"آڈیو کا اشتراک"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"محفوظ ہے"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"غیر منسلک کریں"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"فعال کریں"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"سیٹلائٹ، کنکشن اچھا ہے"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"سیٹلائٹ، کنکشن دستیاب ہے"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"‏سیٹلائٹ SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"‏ایمرجنسی کالز یا SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"دفتری پروفائل"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"کچھ کیلئے دلچسپ لیکن سبھی کیلئے نہیں"</string>
<string name="tuner_warning" msgid="1861736288458481650">"‏سسٹم UI ٹیونر Android صارف انٹر فیس میں ردوبدل کرنے اور اسے حسب ضرورت بنانے کیلئے آپ کو اضافی طریقے دیتا ہے۔ یہ تجرباتی خصوصیات مستقبل کی ریلیزز میں تبدیل ہو سکتی، رک سکتی یا غائب ہو سکتی ہیں۔ احتیاط کے ساتھ آگے بڑھیں۔"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index b0ba287d0364..4b488a255941 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bluetooth ishlatish"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ulangan"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Audio ulashuvi"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Saqlangan"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"uzish"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"faollashtirish"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Sputnik, aloqa sifati yaxshi"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Sputnik, aloqa mavjud"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Sputnik SOS"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Favqulodda chaqiruvlar yoki SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Ish profili"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Diqqat!"</string>
<string name="tuner_warning" msgid="1861736288458481650">"System UI Tuner yordamida siz Android foydalanuvchi interfeysini tuzatish va o‘zingizga moslashtirishingiz mumkin. Ushbu tajribaviy funksiyalar o‘zgarishi, buzilishi yoki keyingi versiyalarda olib tashlanishi mumkin. Ehtiyot bo‘lib davom eting."</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index b6c696741318..2e06f72ba4e6 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Bật Bluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Đã kết nối"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Chia sẻ âm thanh"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Đã lưu"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"ngắt kết nối"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"kích hoạt"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Kết nối vệ tinh tốt"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Hiện có kết nối vệ tinh"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Liên lạc khẩn cấp qua vệ tinh"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Cuộc gọi khẩn cấp hoặc SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Hồ sơ công việc"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Thú vị đối với một số người nhưng không phải tất cả"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Bộ điều hướng giao diện người dùng hệ thống cung cấp thêm cho bạn những cách chỉnh sửa và tùy chỉnh giao diện người dùng Android. Những tính năng thử nghiệm này có thể thay đổi, hỏng hoặc biến mất trong các phiên bản tương lai. Hãy thận trọng khi tiếp tục."</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 9ce05a372a1a..0a96fc208c03 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -107,7 +107,7 @@
<string name="screenrecord_title" msgid="4257171601439507792">"屏幕录制器"</string>
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"正在处理屏幕录制视频"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"持续显示屏幕录制会话通知"</string>
- <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"要录制屏幕?"</string>
+ <string name="screenrecord_permission_dialog_title" msgid="7415261783188749730">"要录制屏幕吗?"</string>
<string name="screenrecord_permission_dialog_option_text_single_app" msgid="1996450687814647583">"录制单个应用"</string>
<string name="screenrecord_permission_dialog_option_text_entire_screen" msgid="2794896384693120020">"录制整个屏幕"</string>
<string name="screenrecord_permission_dialog_warning_entire_screen" msgid="1321758636709366068">"录制整个屏幕时,屏幕上显示的所有内容均会被录制。因此,请务必小心操作,谨防泄露密码、付款信息、消息、照片、音频、视频等。"</string>
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"启用蓝牙"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已连接"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音频分享"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已保存"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"断开连接"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"启用"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"卫星,连接质量良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"卫星,可连接"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"卫星紧急呼救"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"紧急呼叫或紧急求救"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作资料"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"并不适合所有用户"</string>
<string name="tuner_warning" msgid="1861736288458481650">"系统界面调节工具可让您以更多方式调整及定制 Android 界面。在日后推出的版本中,这些实验性功能可能会变更、失效或消失。操作时请务必谨慎。"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index e8532bec6d2c..6b5edff8e525 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"使用藍牙"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已連接"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音訊分享功能"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已儲存"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"解除連結"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"啟動"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛星,連線質素好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可以連線"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"緊急衛星連接"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"緊急電話或 SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作設定檔"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"這只是測試版本,並不包含完整功能"</string>
<string name="tuner_warning" msgid="1861736288458481650">"使用者介面調諧器讓你以更多方法修改和自訂 Android 使用者介面。但請小心,這些實驗功能可能會在日後發佈時更改、分拆或消失。"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index e0493743e811..78cd289907b5 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"使用藍牙"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"已連線"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"音訊分享"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"已儲存"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"取消連結"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"啟用"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"衛星,連線品質良好"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"衛星,可連線"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"緊急衛星連線"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"緊急電話或緊急求救"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"工作資料夾"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"有趣與否,見仁見智"</string>
<string name="tuner_warning" msgid="1861736288458481650">"系統使用者介面調整精靈可讓你透過其他方式,調整及自訂 Android 使用者介面。這些實驗性功能隨著版本更新可能會變更、損壞或消失,執行時請務必謹慎。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index d85db5572f4f..8bcc3edda2cf 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -300,6 +300,8 @@
<string name="turn_on_bluetooth" msgid="5681370462180289071">"Sebenzisa iBluetooth"</string>
<string name="quick_settings_bluetooth_device_connected" msgid="7884777006729260996">"Ixhunyiwe"</string>
<string name="quick_settings_bluetooth_device_audio_sharing" msgid="1496358082943301670">"Ukwabelana Ngokuqoshiwe"</string>
+ <!-- no translation found for quick_settings_bluetooth_device_audio_sharing_or_switch_active (3227408556754456024) -->
+ <skip />
<string name="quick_settings_bluetooth_device_saved" msgid="7549938728928069477">"Ilondoloziwe"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_disconnect" msgid="415980329093277342">"nqamula"</string>
<string name="accessibility_quick_settings_bluetooth_device_tap_to_activate" msgid="3724301751036877403">"yenza kusebenze"</string>
@@ -718,8 +720,7 @@
<string name="accessibility_status_bar_satellite_good_connection" msgid="308079391708578704">"Isethelayithi, uxhumano oluhle"</string>
<string name="accessibility_status_bar_satellite_available" msgid="6514855015496916829">"Isethelayithi, uxhumano luyatholakala"</string>
<string name="satellite_connected_carrier_text" msgid="118524195198532589">"Isethelayithi yokuxhumana ngezimo eziphuthumayo"</string>
- <!-- no translation found for satellite_emergency_only_carrier_text (828510231597991206) -->
- <skip />
+ <string name="satellite_emergency_only_carrier_text" msgid="828510231597991206">"Ikholi ephuthumayo noma i-SOS"</string>
<string name="accessibility_managed_profile" msgid="4703836746209377356">"Iphrofayela yomsebenzi"</string>
<string name="tuner_warning_title" msgid="7721976098452135267">"Kuyajabulisa kwabanye kodwa hhayi bonke"</string>
<string name="tuner_warning" msgid="1861736288458481650">"Isishuni se-UI sesistimu sikunika izindlela ezingeziwe zokuhlobisa nokwenza ngezifiso isixhumanisi sokubona se-Android. Lezi zici zesilingo zingashintsha, zephuke, noma zinyamalale ekukhishweni kwangakusasa. Qhubeka ngokuqaphela."</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 8cf0fb2537cc..a3752640e7ed 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -29,7 +29,7 @@
<color name="status_bar_icons_hover_color_dark">#38000000</color> <!-- 22% black -->
<!-- The dark background color behind the shade -->
- <color name="shade_scrim_background_dark">@*android:color/black</color>
+ <color name="shade_scrim_background_dark">@androidprv:color/system_under_surface_light</color>
<!-- The color of the background in the separated list of the Global Actions menu -->
<color name="global_actions_separated_background">#F5F5F5</color>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index e5750d278bfe..141d03599867 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1751,6 +1751,7 @@
<!-- System UI Dialog -->
<dimen name="dialog_title_text_size">24sp</dimen>
+ <dimen name="dialog_button_side_margin">8dp</dimen>
<!-- Internet panel related dimensions -->
<dimen name="internet_dialog_list_max_height">662dp</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d3d757bcdb46..be74291e705a 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -3699,6 +3699,22 @@
-->
<string name="shortcut_helper_key_combinations_or_separator">or</string>
+ <!-- Keyboard touchpad tutorial scheduler-->
+ <!-- Notification title for launching keyboard tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_keyboard_tutorial_notification_title">Navigate using your keyboard</string>
+ <!-- Notification text for launching keyboard tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_keyboard_tutorial_notification_content">Learn keyboards shortcuts</string>
+
+ <!-- Notification title for launching touchpad tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_touchpad_tutorial_notification_title">Navigate using your touchpad</string>
+ <!-- Notification text for launching keyboard tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_touchpad_tutorial_notification_content">Learn touchpad gestures</string>
+
+ <!-- Notification title for launching keyboard tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_keyboard_touchpad_tutorial_notification_title">Navigate using your keyboard and touchpad</string>
+ <!-- Notification text for launching keyboard tutorial [CHAR_LIMIT=100] -->
+ <string name="launch_keyboard_touchpad_tutorial_notification_content">Learn touchpad gestures, keyboards shortcuts, and more</string>
+
<!-- TOUCHPAD TUTORIAL-->
<!-- Label for button opening tutorial for back gesture on touchpad [CHAR LIMIT=NONE] -->
<string name="touchpad_tutorial_back_gesture_button">Back gesture</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 3ef624365594..a02c35461031 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -505,14 +505,14 @@
<item name="onSurfaceVariant">?androidprv:attr/materialColorOnSurfaceVariant</item>
<item name="outline">?androidprv:attr/materialColorOutline</item>
- <item name="shadeActive">@color/material_dynamic_primary90</item>
- <item name="onShadeActive">@color/material_dynamic_primary10</item>
- <item name="onShadeActiveVariant">@color/material_dynamic_primary30</item>
- <item name="shadeInactive">@color/material_dynamic_neutral20</item>
- <item name="onShadeInactive">@color/material_dynamic_neutral90</item>
- <item name="onShadeInactiveVariant">@color/material_dynamic_neutral_variant80</item>
- <item name="shadeDisabled">@color/shade_disabled</item>
- <item name="underSurface">@color/material_dynamic_neutral0</item>
+ <item name="shadeActive">?androidprv:attr/customColorShadeActive</item>
+ <item name="onShadeActive">?androidprv:attr/customColorOnShadeActive</item>
+ <item name="onShadeActiveVariant">?androidprv:attr/customColorOnShadeActiveVariant</item>
+ <item name="shadeInactive">?androidprv:attr/customColorShadeInactive</item>
+ <item name="onShadeInactive">?androidprv:attr/customColorOnShadeInactive</item>
+ <item name="onShadeInactiveVariant">?androidprv:attr/customColorOnShadeInactiveVariant</item>
+ <item name="shadeDisabled">?androidprv:attr/customColorShadeDisabled</item>
+ <item name="underSurface">?androidprv:attr/customColorUnderSurface</item>
<item name="android:itemTextAppearance">@style/Control.MenuItem</item>
</style>
diff --git a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
index 77338410642c..5e36539ecbec 100644
--- a/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
+++ b/packages/SystemUI/src/com/android/keyguard/EmergencyButtonController.java
@@ -17,6 +17,7 @@
package com.android.keyguard;
import static com.android.systemui.DejankUtils.whitelistIpcs;
+import static com.android.systemui.Flags.msdlFeedback;
import android.annotation.SuppressLint;
import android.app.ActivityOptions;
@@ -46,6 +47,9 @@ import com.android.systemui.user.domain.interactor.SelectedUserInteractor;
import com.android.systemui.util.EmergencyDialerConstants;
import com.android.systemui.util.ViewController;
+import com.google.android.msdl.data.model.MSDLToken;
+import com.google.android.msdl.domain.MSDLPlayer;
+
import java.util.concurrent.Executor;
import javax.inject.Inject;
@@ -67,6 +71,7 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
private final Executor mMainExecutor;
private final Executor mBackgroundExecutor;
private final SelectedUserInteractor mSelectedUserInteractor;
+ private final MSDLPlayer mMSDLPlayer;
private final KeyguardUpdateMonitorCallback mInfoCallback =
new KeyguardUpdateMonitorCallback() {
@@ -99,7 +104,8 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
MetricsLogger metricsLogger,
LockPatternUtils lockPatternUtils,
Executor mainExecutor, Executor backgroundExecutor,
- SelectedUserInteractor selectedUserInteractor) {
+ SelectedUserInteractor selectedUserInteractor,
+ MSDLPlayer msdlPlayer) {
super(view);
mConfigurationController = configurationController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -112,6 +118,7 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
mMainExecutor = mainExecutor;
mBackgroundExecutor = backgroundExecutor;
mSelectedUserInteractor = selectedUserInteractor;
+ mMSDLPlayer = msdlPlayer;
}
@Override
@@ -165,6 +172,9 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
@SuppressLint("MissingPermission")
public void takeEmergencyCallAction() {
mMetricsLogger.action(MetricsEvent.ACTION_EMERGENCY_CALL);
+ if (msdlFeedback()) {
+ mMSDLPlayer.playToken(MSDLToken.KEYPRESS_RETURN, null);
+ }
if (mPowerManager != null) {
mPowerManager.userActivity(SystemClock.uptimeMillis(), true);
}
@@ -221,6 +231,7 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
private final Executor mMainExecutor;
private final Executor mBackgroundExecutor;
private final SelectedUserInteractor mSelectedUserInteractor;
+ private final MSDLPlayer mMSDLPlayer;
@Inject
public Factory(ConfigurationController configurationController,
@@ -233,7 +244,8 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
LockPatternUtils lockPatternUtils,
@Main Executor mainExecutor,
@Background Executor backgroundExecutor,
- SelectedUserInteractor selectedUserInteractor) {
+ SelectedUserInteractor selectedUserInteractor,
+ MSDLPlayer msdlPlayer) {
mConfigurationController = configurationController;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
@@ -246,6 +258,7 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
mMainExecutor = mainExecutor;
mBackgroundExecutor = backgroundExecutor;
mSelectedUserInteractor = selectedUserInteractor;
+ mMSDLPlayer = msdlPlayer;
}
/** Construct an {@link com.android.keyguard.EmergencyButtonController}. */
@@ -253,7 +266,7 @@ public class EmergencyButtonController extends ViewController<EmergencyButton> {
return new EmergencyButtonController(view, mConfigurationController,
mKeyguardUpdateMonitor, mPowerManager, mActivityTaskManager, mShadeController,
mTelecomManager, mMetricsLogger, mLockPatternUtils, mMainExecutor,
- mBackgroundExecutor, mSelectedUserInteractor);
+ mBackgroundExecutor, mSelectedUserInteractor, mMSDLPlayer);
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 61f9800c351b..2d28a189f84d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -35,7 +35,6 @@ import static com.android.systemui.flags.Flags.LOCKSCREEN_ENABLE_LANDSCAPE;
import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
-import android.app.admin.flags.Flags;
import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
@@ -1140,12 +1139,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
int remainingBeforeWipe, int failedAttempts) {
int userType = USER_TYPE_PRIMARY;
if (expiringUserId == userId) {
- int primaryUser = UserHandle.USER_SYSTEM;
- if (Flags.headlessSingleUserFixes()) {
- if (mainUserId != null) {
- primaryUser = mainUserId;
- }
- }
+ int primaryUser = mainUserId != null ? mainUserId : UserHandle.USER_SYSTEM;
// TODO: http://b/23522538
if (expiringUserId != primaryUser) {
userType = USER_TYPE_SECONDARY_USER;
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt b/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt
index b0314d8fab84..476d54b42adc 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/ambient/dagger/AmbientModule.kt
@@ -32,5 +32,6 @@ import dagger.Module
interface AmbientModule {
companion object {
const val TOUCH_HANDLERS = "touch_handlers"
+ const val LOGGING_NAME = "logging_name"
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
index 1be6f9e7ca4f..0898134a3db8 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/TouchMonitor.java
@@ -18,6 +18,7 @@ package com.android.systemui.ambient.touch;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static com.android.systemui.ambient.dagger.AmbientModule.LOGGING_NAME;
import static com.android.systemui.shared.Flags.bouncerAreaExclusion;
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
@@ -44,6 +45,9 @@ import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.DisplayId;
import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.log.LogBuffer;
+import com.android.systemui.log.core.Logger;
+import com.android.systemui.log.dagger.CommunalTouchLog;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.util.display.DisplayHelper;
@@ -62,6 +66,8 @@ import java.util.function.Consumer;
import java.util.stream.Collectors;
import javax.inject.Inject;
+import javax.inject.Named;
+
/**
* {@link TouchMonitor} is responsible for monitoring touches and gestures over the
@@ -73,6 +79,7 @@ public class TouchMonitor {
// This executor is used to protect {@code mActiveTouchSessions} from being modified
// concurrently. Any operation that adds or removes values should use this executor.
public String TAG = "DreamOverlayTouchMonitor";
+ private final Logger mLogger;
private final Executor mMainExecutor;
private final Executor mBackgroundExecutor;
@@ -116,6 +123,11 @@ public class TouchMonitor {
TouchSessionImpl touchSessionImpl) {
return CallbackToFutureAdapter.getFuture(completer -> {
mMainExecutor.execute(() -> {
+ mLogger.i(msg -> "Session popped, hashCode: " + msg.getInt1(), msg -> {
+ msg.setInt1(touchSessionImpl.hashCode());
+ return kotlin.Unit.INSTANCE;
+ });
+
if (mActiveTouchSessions.remove(touchSessionImpl)) {
touchSessionImpl.onRemoved();
@@ -269,6 +281,7 @@ public class TouchMonitor {
* When invoked, instantiates a new {@link InputSession} to monitor touch events.
*/
private void startMonitoring() {
+ mLogger.i("startMonitoring(): monitoring started");
stopMonitoring(true);
if (bouncerAreaExclusion()) {
@@ -322,6 +335,12 @@ public class TouchMonitor {
}
if (!mActiveTouchSessions.isEmpty() && !force) {
+ mLogger.i(msg -> "stopMonitoring(): waiting for sessions to end: " + msg.getStr1(),
+ msg -> {
+ msg.setStr1(mActiveTouchSessions.stream().map(Object::hashCode).map(
+ Object::toString).collect(Collectors.joining(",")));
+ return kotlin.Unit.INSTANCE;
+ });
mStopMonitoringPending = true;
return;
}
@@ -341,6 +360,8 @@ public class TouchMonitor {
mCurrentInputSession.dispose();
mCurrentInputSession = null;
mStopMonitoringPending = false;
+
+ mLogger.i("stopMonitoring(): monitoring finished");
}
@@ -405,12 +426,29 @@ public class TouchMonitor {
// created so the
// final session is correct.
sessionMap.forEach((dreamTouchHandler, touchSession)
- -> dreamTouchHandler.onSessionStart(touchSession));
+ -> {
+ if (ev instanceof MotionEvent motionEvent) {
+ int x = Math.round(motionEvent.getX());
+ int y = Math.round(motionEvent.getY());
+ mLogger.i(
+ msg -> "Session start, handler: " + msg.getStr1() + ", x: "
+ + msg.getLong1() + ", y: " + msg.getLong2()
+ + ", hashCode: " + msg.getInt1(), msg -> {
+ msg.setStr1(
+ dreamTouchHandler.getClass().getSimpleName());
+ msg.setLong1(x);
+ msg.setLong2(y);
+ msg.setInt1(touchSession.hashCode());
+ return kotlin.Unit.INSTANCE;
+ });
+ }
+ dreamTouchHandler.onSessionStart(touchSession);
+ });
}
// Find active sessions and invoke on InputEvent.
mActiveTouchSessions.stream()
- .map(touchSessionStack -> touchSessionStack.getEventListeners())
+ .map(TouchSessionImpl::getEventListeners)
.flatMap(Collection::stream)
.forEach(inputEventListener -> inputEventListener.onInputEvent(ev));
}
@@ -526,6 +564,8 @@ public class TouchMonitor {
* returned.
* @param handlers This set represents the {@link TouchHandler} instances that will
* participate in touch handling.
+ * @param loggingName Identifying string for this {@link TouchMonitor} that will be used
+ * when logging to {@link CommunalTouchLog}.
*/
@Inject
public TouchMonitor(
@@ -537,7 +577,9 @@ public class TouchMonitor {
ConfigurationInteractor configurationInteractor,
Set<TouchHandler> handlers,
IWindowManager windowManagerService,
- @DisplayId int displayId) {
+ @DisplayId int displayId,
+ @Named(LOGGING_NAME) String loggingName,
+ @CommunalTouchLog LogBuffer logBuffer) {
mDisplayId = displayId;
mHandlers = handlers;
mInputSessionFactory = inputSessionFactory;
@@ -547,6 +589,7 @@ public class TouchMonitor {
mDisplayHelper = displayHelper;
mWindowManagerService = windowManagerService;
mConfigurationInteractor = configurationInteractor;
+ mLogger = new Logger(logBuffer, loggingName + ":TouchMonitor");
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt
index 390e53bb5782..ba552c3b7903 100644
--- a/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/ambient/touch/dagger/AmbientTouchComponent.kt
@@ -16,6 +16,7 @@
package com.android.systemui.ambient.touch.dagger
import androidx.lifecycle.LifecycleOwner
+import com.android.systemui.ambient.dagger.AmbientModule.Companion.LOGGING_NAME
import com.android.systemui.ambient.dagger.AmbientModule.Companion.TOUCH_HANDLERS
import com.android.systemui.ambient.touch.TouchHandler
import com.android.systemui.ambient.touch.TouchMonitor
@@ -36,7 +37,8 @@ interface AmbientTouchComponent {
@BindsInstance lifecycleOwner: LifecycleOwner,
@BindsInstance
@Named(TOUCH_HANDLERS)
- touchHandlers: Set<@JvmSuppressWildcards TouchHandler>
+ touchHandlers: Set<@JvmSuppressWildcards TouchHandler>,
+ @BindsInstance @Named(LOGGING_NAME) loggingName: String,
): AmbientTouchComponent
}
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
index fcba425f0956..3080e1978b2a 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
@@ -16,7 +16,6 @@
package com.android.systemui.authentication.domain.interactor
-import android.app.admin.flags.Flags
import android.os.UserHandle
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.LockPatternView
@@ -289,12 +288,7 @@ constructor(
private suspend fun getWipeTarget(): WipeTarget {
// Check which profile has the strictest policy for failed authentication attempts.
val userToBeWiped = repository.getProfileWithMinFailedUnlockAttemptsForWipe()
- val primaryUser =
- if (Flags.headlessSingleUserFixes()) {
- selectedUserInteractor.getMainUserId() ?: UserHandle.USER_SYSTEM
- } else {
- UserHandle.USER_SYSTEM
- }
+ val primaryUser = selectedUserInteractor.getMainUserId() ?: UserHandle.USER_SYSTEM
return when (userToBeWiped) {
selectedUserInteractor.getSelectedUserId() ->
if (userToBeWiped == primaryUser) {
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
index cc8dce7938aa..49dadcefb276 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/BouncerViewBinder.kt
@@ -2,13 +2,11 @@ package com.android.systemui.bouncer.ui.binder
import android.view.ViewGroup
import com.android.keyguard.KeyguardMessageAreaController
-import com.android.keyguard.ViewMediatorCallback
import com.android.keyguard.dagger.KeyguardBouncerComponent
-import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlags
import com.android.systemui.bouncer.ui.BouncerDialogFactory
+import com.android.systemui.bouncer.ui.viewmodel.BouncerContainerViewModel
import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
import com.android.systemui.bouncer.ui.viewmodel.KeyguardBouncerViewModel
import com.android.systemui.dagger.SysUISingleton
@@ -39,12 +37,9 @@ constructor(
data class ComposeBouncerDependencies
@Inject
constructor(
- val legacyInteractor: PrimaryBouncerInteractor,
val viewModelFactory: BouncerSceneContentViewModel.Factory,
val dialogFactory: BouncerDialogFactory,
- val authenticationInteractor: AuthenticationInteractor,
- val viewMediatorCallback: ViewMediatorCallback?,
- val selectedUserInteractor: SelectedUserInteractor,
+ val bouncerContainerViewModelFactory: BouncerContainerViewModel.Factory,
)
/**
@@ -63,12 +58,9 @@ constructor(
val deps = composeBouncerDependencies.get()
ComposeBouncerViewBinder.bind(
view,
- deps.legacyInteractor,
deps.viewModelFactory,
deps.dialogFactory,
- deps.authenticationInteractor,
- deps.selectedUserInteractor,
- deps.viewMediatorCallback,
+ deps.bouncerContainerViewModelFactory,
)
} else {
val deps = legacyBouncerDependencies.get()
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
index c4bbd9cf0d9f..b5e54d5f079b 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/binder/ComposeBouncerViewBinder.kt
@@ -5,89 +5,55 @@ import androidx.activity.OnBackPressedDispatcher
import androidx.activity.OnBackPressedDispatcherOwner
import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.compose.ui.platform.ComposeView
-import androidx.core.view.isVisible
+import androidx.core.view.isGone
import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.repeatOnLifecycle
-import com.android.keyguard.ViewMediatorCallback
-import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
-import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.ui.BouncerDialogFactory
import com.android.systemui.bouncer.ui.composable.BouncerContainer
+import com.android.systemui.bouncer.ui.viewmodel.BouncerContainerViewModel
import com.android.systemui.bouncer.ui.viewmodel.BouncerSceneContentViewModel
+import com.android.systemui.lifecycle.WindowLifecycleState
import com.android.systemui.lifecycle.repeatWhenAttached
-import com.android.systemui.user.domain.interactor.SelectedUserInteractor
-import kotlinx.coroutines.flow.collectLatest
-import kotlinx.coroutines.launch
+import com.android.systemui.lifecycle.setSnapshotBinding
+import com.android.systemui.lifecycle.viewModel
+import kotlinx.coroutines.awaitCancellation
/** View binder responsible for binding the compose version of the bouncer. */
object ComposeBouncerViewBinder {
fun bind(
view: ViewGroup,
- legacyInteractor: PrimaryBouncerInteractor,
viewModelFactory: BouncerSceneContentViewModel.Factory,
dialogFactory: BouncerDialogFactory,
- authenticationInteractor: AuthenticationInteractor,
- selectedUserInteractor: SelectedUserInteractor,
- viewMediatorCallback: ViewMediatorCallback?,
+ bouncerContainerViewModelFactory: BouncerContainerViewModel.Factory,
) {
- view.addView(
- ComposeView(view.context).apply {
- repeatWhenAttached {
- repeatOnLifecycle(Lifecycle.State.CREATED) {
- setViewTreeOnBackPressedDispatcherOwner(
- object : OnBackPressedDispatcherOwner {
- override val onBackPressedDispatcher =
- OnBackPressedDispatcher().apply {
- setOnBackInvokedDispatcher(
- view.viewRootImpl.onBackInvokedDispatcher
- )
- }
-
- override val lifecycle: Lifecycle =
- this@repeatWhenAttached.lifecycle
- }
- )
- setContent { BouncerContainer(viewModelFactory, dialogFactory) }
- }
- }
- }
- )
-
view.repeatWhenAttached {
- repeatOnLifecycle(Lifecycle.State.CREATED) {
- launch {
- legacyInteractor.isShowing.collectLatest { bouncerShowing ->
- view.isVisible = bouncerShowing
- }
- }
+ view.viewModel(
+ minWindowLifecycleState = WindowLifecycleState.ATTACHED,
+ factory = { bouncerContainerViewModelFactory.create() },
+ traceName = "ComposeBouncerViewBinder",
+ ) { viewModel ->
+ try {
+ view.setViewTreeOnBackPressedDispatcherOwner(
+ object : OnBackPressedDispatcherOwner {
+ override val onBackPressedDispatcher =
+ OnBackPressedDispatcher().apply {
+ setOnBackInvokedDispatcher(
+ view.viewRootImpl.onBackInvokedDispatcher
+ )
+ }
- launch {
- authenticationInteractor.onAuthenticationResult.collectLatest {
- authenticationSucceeded ->
- if (authenticationSucceeded) {
- // Some dismiss actions require that keyguard be dismissed right away or
- // deferred until something else later on dismisses keyguard (eg. end of
- // a hide animation).
- val deferKeyguardDone =
- legacyInteractor.bouncerDismissAction?.onDismissAction?.onDismiss()
- legacyInteractor.setDismissAction(null, null)
+ override val lifecycle: Lifecycle = this@repeatWhenAttached.lifecycle
+ }
+ )
- viewMediatorCallback?.let {
- val selectedUserId = selectedUserInteractor.getSelectedUserId()
- if (deferKeyguardDone == true) {
- it.keyguardDonePending(selectedUserId)
- } else {
- it.keyguardDone(selectedUserId)
- }
- }
+ view.addView(
+ ComposeView(view.context).apply {
+ setContent { BouncerContainer(viewModelFactory, dialogFactory) }
}
- }
- }
- launch {
- legacyInteractor.startingDisappearAnimation.collectLatest {
- it.run()
- legacyInteractor.hide()
- }
+ )
+ view.setSnapshotBinding { view.isGone = !viewModel.isVisible }
+ awaitCancellation()
+ } finally {
+ view.removeAllViews()
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt
new file mode 100644
index 000000000000..d223657aa74d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerContainerViewModel.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.bouncer.ui.viewmodel
+
+import androidx.compose.runtime.getValue
+import com.android.keyguard.ViewMediatorCallback
+import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
+import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
+import com.android.systemui.lifecycle.ExclusiveActivatable
+import com.android.systemui.lifecycle.Hydrator
+import com.android.systemui.user.domain.interactor.SelectedUserInteractor
+import dagger.assisted.AssistedFactory
+import dagger.assisted.AssistedInject
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.launch
+
+class BouncerContainerViewModel
+@AssistedInject
+constructor(
+ private val legacyInteractor: PrimaryBouncerInteractor,
+ private val authenticationInteractor: AuthenticationInteractor,
+ private val selectedUserInteractor: SelectedUserInteractor,
+ private val viewMediatorCallback: ViewMediatorCallback?,
+) : ExclusiveActivatable() {
+
+ private val hydrator = Hydrator("BouncerContainerViewModel")
+
+ val isVisible: Boolean by
+ hydrator.hydratedStateOf(traceName = "isVisible", source = legacyInteractor.isShowing)
+
+ override suspend fun onActivated(): Nothing {
+ coroutineScope {
+ launch {
+ authenticationInteractor.onAuthenticationResult.collect { authenticationSucceeded ->
+ if (authenticationSucceeded) {
+ // Some dismiss actions require that keyguard be dismissed right away or
+ // deferred until something else later on dismisses keyguard (eg. end of
+ // a hide animation).
+ val deferKeyguardDone =
+ legacyInteractor.bouncerDismissAction?.onDismissAction?.onDismiss()
+ legacyInteractor.setDismissAction(null, null)
+
+ viewMediatorCallback?.let {
+ val selectedUserId = selectedUserInteractor.getSelectedUserId()
+ if (deferKeyguardDone == true) {
+ it.keyguardDonePending(selectedUserId)
+ } else {
+ it.keyguardDone(selectedUserId)
+ }
+ }
+ }
+ }
+ }
+
+ launch {
+ legacyInteractor.startingDisappearAnimation.collect {
+ it.run()
+ legacyInteractor.hide()
+ }
+ }
+
+ hydrator.activate()
+ }
+ }
+
+ @AssistedFactory
+ interface Factory {
+ fun create(): BouncerContainerViewModel
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModel.kt
index 2d57e5b4f204..4fe6fc69e8be 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerUserActionsViewModel.kt
@@ -22,7 +22,7 @@ import com.android.compose.animation.scene.SwipeDirection
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.map
@@ -31,11 +31,11 @@ import kotlinx.coroutines.flow.map
* Models UI state for user actions that can lead to navigation to other scenes when showing the
* bouncer scene.
*/
-class BouncerSceneActionsViewModel
+class BouncerUserActionsViewModel
@AssistedInject
constructor(
private val bouncerInteractor: BouncerInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
bouncerInteractor.dismissDestination
@@ -50,6 +50,6 @@ constructor(
@AssistedFactory
interface Factory {
- fun create(): BouncerSceneActionsViewModel
+ fun create(): BouncerUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index d2caefd3b552..e1ba93c75aad 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -76,7 +76,6 @@ public class BrightLineFalsingManager implements FalsingManager {
private final boolean mTestHarness;
private final MetricsLogger mMetricsLogger;
private int mIsFalseTouchCalls;
- private FeatureFlags mFeatureFlags;
private static final Queue<String> RECENT_INFO_LOG =
new ArrayDeque<>(RECENT_INFO_LOG_SIZE + 1);
private static final Queue<DebugSwipeRecord> RECENT_SWIPES =
@@ -186,8 +185,7 @@ public class BrightLineFalsingManager implements FalsingManager {
DoubleTapClassifier doubleTapClassifier, HistoryTracker historyTracker,
KeyguardStateController keyguardStateController,
AccessibilityManager accessibilityManager,
- @TestHarness boolean testHarness,
- FeatureFlags featureFlags) {
+ @TestHarness boolean testHarness) {
mDataProvider = falsingDataProvider;
mMetricsLogger = metricsLogger;
mClassifiers = classifiers;
@@ -198,7 +196,6 @@ public class BrightLineFalsingManager implements FalsingManager {
mKeyguardStateController = keyguardStateController;
mAccessibilityManager = accessibilityManager;
mTestHarness = testHarness;
- mFeatureFlags = featureFlags;
mDataProvider.addSessionListener(mSessionListener);
mDataProvider.addGestureCompleteListener(mGestureFinalizedListener);
@@ -399,8 +396,7 @@ public class BrightLineFalsingManager implements FalsingManager {
|| mDataProvider.isA11yAction()
|| mDataProvider.isFromTrackpad()
|| mDataProvider.isFromKeyboard()
- || (mFeatureFlags.isEnabled(Flags.FALSING_OFF_FOR_UNFOLDED)
- && mDataProvider.isUnfolded());
+ || mDataProvider.isUnfolded();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 1c263ae4b2bb..ae2d4012b83b 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -475,7 +475,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
mLifecycleOwner,
new HashSet<>(Arrays.asList(
dreamComplicationComponent.getHideComplicationTouchHandler(),
- dreamOverlayComponent.getCommunalTouchHandler())));
+ dreamOverlayComponent.getCommunalTouchHandler())), TAG);
setLifecycleStateLocked(Lifecycle.State.STARTED);
diff --git a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
index 87eeebf333e9..3105527eb9b1 100644
--- a/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/education/domain/interactor/KeyboardTouchpadEduInteractor.kt
@@ -24,8 +24,6 @@ import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLoggin
import com.android.systemui.contextualeducation.GestureType
import com.android.systemui.contextualeducation.GestureType.ALL_APPS
import com.android.systemui.contextualeducation.GestureType.BACK
-import com.android.systemui.contextualeducation.GestureType.HOME
-import com.android.systemui.contextualeducation.GestureType.OVERVIEW
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.education.dagger.ContextualEducationModule.EduClock
@@ -68,11 +66,9 @@ constructor(
private val keyboardShortcutTriggered: Flow<GestureType> = conflatedCallbackFlow {
val listener = KeyGestureEventListener { event ->
+ // Only store keyboard shortcut time for gestures providing keyboard education
val shortcutType =
when (event.keyGestureType) {
- KeyGestureEvent.KEY_GESTURE_TYPE_BACK -> BACK
- KeyGestureEvent.KEY_GESTURE_TYPE_HOME -> HOME
- KeyGestureEvent.KEY_GESTURE_TYPE_RECENT_APPS -> OVERVIEW
KeyGestureEvent.KEY_GESTURE_TYPE_ALL_APPS -> ALL_APPS
else -> null
}
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index bb73f569d945..95cd9eb4ae4b 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -98,9 +98,6 @@ object Flags {
@JvmField
val AUTO_PIN_CONFIRMATION = releasedFlag("auto_pin_confirmation", "auto_pin_confirmation")
- // TODO(b/262859270): Tracking Bug
- @JvmField val FALSING_OFF_FOR_UNFOLDED = releasedFlag("falsing_off_for_unfolded")
-
/** Enables code to show contextual loyalty cards in wallet entrypoints */
// TODO(b/294110497): Tracking Bug
@JvmField
@@ -203,12 +200,6 @@ object Flags {
@JvmField
val INCOMPATIBLE_CHARGING_BATTERY_ICON = releasedFlag("incompatible_charging_battery_icon")
- // TODO(b/293585143): Tracking Bug
- val INSTANT_TETHER = releasedFlag("instant_tether")
-
- // TODO(b/294588085): Tracking Bug
- val WIFI_SECONDARY_NETWORKS = releasedFlag("wifi_secondary_networks")
-
// TODO(b/290676905): Tracking Bug
val NEW_SHADE_CARRIER_GROUP_MOBILE_ICONS = releasedFlag("new_shade_carrier_group_mobile_icons")
@@ -233,9 +224,6 @@ object Flags {
// TODO(b/254512697): Tracking Bug
val MEDIA_TAP_TO_TRANSFER = releasedFlag("media_tap_to_transfer")
- // TODO(b/254512502): Tracking Bug
- val MEDIA_SESSION_ACTIONS = unreleasedFlag("media_session_actions")
-
// TODO(b/254512654): Tracking Bug
@JvmField val DREAM_MEDIA_COMPLICATION = unreleasedFlag("dream_media_complication")
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt
index e8e1dd4c85d0..7ecacdc7cf16 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/KeyboardTouchpadTutorialCoreStartable.kt
@@ -18,20 +18,20 @@ package com.android.systemui.inputdevice.tutorial
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor
+import com.android.systemui.inputdevice.tutorial.ui.TutorialNotificationCoordinator
import com.android.systemui.shared.Flags.newTouchpadGesturesTutorial
import dagger.Lazy
import javax.inject.Inject
-/** A [CoreStartable] to launch a scheduler for keyboard and touchpad education */
+/** A [CoreStartable] to launch a scheduler for keyboard and touchpad tutorial notification */
@SysUISingleton
class KeyboardTouchpadTutorialCoreStartable
@Inject
-constructor(private val tutorialSchedulerInteractor: Lazy<TutorialSchedulerInteractor>) :
+constructor(private val tutorialNotificationCoordinator: Lazy<TutorialNotificationCoordinator>) :
CoreStartable {
override fun start() {
if (newTouchpadGesturesTutorial()) {
- tutorialSchedulerInteractor.get().start()
+ tutorialNotificationCoordinator.get().start()
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
index a8d7dad42a93..cfc913fbc89b 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractor.kt
@@ -17,9 +17,7 @@
package com.android.systemui.inputdevice.tutorial.domain.interactor
import android.os.SystemProperties
-import android.util.Log
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType
import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.KEYBOARD
import com.android.systemui.inputdevice.tutorial.data.repository.DeviceType.TOUCHPAD
@@ -31,23 +29,22 @@ import java.time.Instant
import javax.inject.Inject
import kotlin.time.Duration.Companion.hours
import kotlin.time.toKotlinDuration
-import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
-import kotlinx.coroutines.launch
/**
- * When the first time a keyboard or touchpad is connected, wait for [LAUNCH_DELAY], then launch the
- * tutorial as soon as there's a connected device
+ * When the first time a keyboard or touchpad is connected, wait for [LAUNCH_DELAY], and as soon as
+ * there's a connected device, show a notification to launch the tutorial.
*/
@SysUISingleton
class TutorialSchedulerInteractor
@Inject
constructor(
- @Background private val backgroundScope: CoroutineScope,
keyboardRepository: KeyboardRepository,
touchpadRepository: TouchpadRepository,
private val repo: TutorialSchedulerRepository
@@ -58,17 +55,6 @@ constructor(
TOUCHPAD to touchpadRepository.isAnyTouchpadConnected
)
- fun start() {
- backgroundScope.launch {
- // Merging two flows to ensure that launch tutorial is launched consecutively in order
- // to avoid race condition
- merge(touchpadScheduleFlow, keyboardScheduleFlow).collect {
- val tutorialType = resolveTutorialType(it)
- launchTutorial(tutorialType)
- }
- }
- }
-
private val touchpadScheduleFlow = flow {
if (!repo.isLaunched(TOUCHPAD)) {
schedule(TOUCHPAD)
@@ -95,14 +81,19 @@ constructor(
private suspend fun waitForDeviceConnection(deviceType: DeviceType) =
isAnyDeviceConnected[deviceType]!!.filter { it }.first()
- private suspend fun launchTutorial(tutorialType: TutorialType) {
- if (tutorialType == TutorialType.KEYBOARD || tutorialType == TutorialType.BOTH)
- repo.updateLaunchTime(KEYBOARD, Instant.now())
- if (tutorialType == TutorialType.TOUCHPAD || tutorialType == TutorialType.BOTH)
- repo.updateLaunchTime(TOUCHPAD, Instant.now())
- // TODO: launch tutorial
- Log.d(TAG, "Launch tutorial for $tutorialType")
- }
+ // Merging two flows ensures that tutorial is launched consecutively to avoid race condition
+ val tutorials: Flow<TutorialType> =
+ merge(touchpadScheduleFlow, keyboardScheduleFlow).map {
+ val tutorialType = resolveTutorialType(it)
+
+ // TODO: notifying time is not oobe launching time - move these updates into oobe
+ if (tutorialType == TutorialType.KEYBOARD || tutorialType == TutorialType.BOTH)
+ repo.updateLaunchTime(KEYBOARD, Instant.now())
+ if (tutorialType == TutorialType.TOUCHPAD || tutorialType == TutorialType.BOTH)
+ repo.updateLaunchTime(TOUCHPAD, Instant.now())
+
+ tutorialType
+ }
private suspend fun resolveTutorialType(deviceType: DeviceType): TutorialType {
// Resolve the type of tutorial depending on which device are connected when the tutorial is
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt
new file mode 100644
index 000000000000..5d9dda3899cd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/TutorialNotificationCoordinator.kt
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.inputdevice.tutorial.ui
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import androidx.core.app.NotificationCompat
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor
+import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor.Companion.TAG
+import com.android.systemui.inputdevice.tutorial.domain.interactor.TutorialSchedulerInteractor.TutorialType
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_BOTH
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEY
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_KEYBOARD
+import com.android.systemui.inputdevice.tutorial.ui.view.KeyboardTouchpadTutorialActivity.Companion.INTENT_TUTORIAL_TYPE_TOUCHPAD
+import com.android.systemui.res.R
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.launch
+
+/** When the scheduler is due, show a notification to launch tutorial */
+@SysUISingleton
+class TutorialNotificationCoordinator
+@Inject
+constructor(
+ @Background private val backgroundScope: CoroutineScope,
+ @Application private val context: Context,
+ private val tutorialSchedulerInteractor: TutorialSchedulerInteractor,
+ private val notificationManager: NotificationManager
+) {
+ fun start() {
+ backgroundScope.launch {
+ tutorialSchedulerInteractor.tutorials.collect { showNotification(it) }
+ }
+ }
+
+ // By sharing the same tag and id, we update the content of existing notification instead of
+ // creating multiple notifications
+ private fun showNotification(tutorialType: TutorialType) {
+ if (tutorialType == TutorialType.NONE) return
+
+ if (notificationManager.getNotificationChannel(CHANNEL_ID) == null)
+ createNotificationChannel()
+
+ // Replace "System UI" app name with "Android System"
+ val extras = Bundle()
+ extras.putString(
+ Notification.EXTRA_SUBSTITUTE_APP_NAME,
+ context.getString(com.android.internal.R.string.android_system_label)
+ )
+
+ val info = getNotificationInfo(tutorialType)!!
+ val notification =
+ NotificationCompat.Builder(context, CHANNEL_ID)
+ .setSmallIcon(R.drawable.ic_settings)
+ .setContentTitle(info.title)
+ .setContentText(info.text)
+ .setContentIntent(createPendingIntent(info.type))
+ .setPriority(NotificationCompat.PRIORITY_DEFAULT)
+ .setAutoCancel(true)
+ .addExtras(extras)
+ .build()
+
+ notificationManager.notify(TAG, NOTIFICATION_ID, notification)
+ }
+
+ private fun createNotificationChannel() {
+ val channel =
+ NotificationChannel(
+ CHANNEL_ID,
+ context.getString(com.android.internal.R.string.android_system_label),
+ NotificationManager.IMPORTANCE_DEFAULT
+ )
+ notificationManager.createNotificationChannel(channel)
+ }
+
+ private fun createPendingIntent(tutorialType: String): PendingIntent {
+ val intent =
+ Intent(context, KeyboardTouchpadTutorialActivity::class.java).apply {
+ putExtra(INTENT_TUTORIAL_TYPE_KEY, tutorialType)
+ flags = Intent.FLAG_ACTIVITY_NEW_TASK
+ }
+ return PendingIntent.getActivity(
+ context,
+ /* requestCode= */ 0,
+ intent,
+ PendingIntent.FLAG_IMMUTABLE
+ )
+ }
+
+ private data class NotificationInfo(val title: String, val text: String, val type: String)
+
+ private fun getNotificationInfo(tutorialType: TutorialType): NotificationInfo? =
+ when (tutorialType) {
+ TutorialType.KEYBOARD ->
+ NotificationInfo(
+ context.getString(R.string.launch_keyboard_tutorial_notification_title),
+ context.getString(R.string.launch_keyboard_tutorial_notification_content),
+ INTENT_TUTORIAL_TYPE_KEYBOARD
+ )
+ TutorialType.TOUCHPAD ->
+ NotificationInfo(
+ context.getString(R.string.launch_touchpad_tutorial_notification_title),
+ context.getString(R.string.launch_touchpad_tutorial_notification_content),
+ INTENT_TUTORIAL_TYPE_TOUCHPAD
+ )
+ TutorialType.BOTH ->
+ NotificationInfo(
+ context.getString(
+ R.string.launch_keyboard_touchpad_tutorial_notification_title
+ ),
+ context.getString(
+ R.string.launch_keyboard_touchpad_tutorial_notification_content
+ ),
+ INTENT_TUTORIAL_TYPE_BOTH
+ )
+ TutorialType.NONE -> null
+ }
+
+ companion object {
+ private const val CHANNEL_ID = "TutorialSchedulerNotificationChannel"
+ private const val NOTIFICATION_ID = 5566
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
index 8debe7975197..1adc285e6bb5 100644
--- a/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/inputdevice/tutorial/ui/view/KeyboardTouchpadTutorialActivity.kt
@@ -54,6 +54,7 @@ constructor(
const val INTENT_TUTORIAL_TYPE_KEY = "tutorial_type"
const val INTENT_TUTORIAL_TYPE_TOUCHPAD = "touchpad"
const val INTENT_TUTORIAL_TYPE_KEYBOARD = "keyboard"
+ const val INTENT_TUTORIAL_TYPE_BOTH = "both"
}
private val vm by
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
index 7899971484f1..5bb7b6425729 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt
@@ -22,7 +22,6 @@ import android.annotation.DrawableRes
import android.annotation.SuppressLint
import android.graphics.Point
import android.graphics.Rect
-import android.os.VibrationAttributes
import android.util.Log
import android.view.HapticFeedbackConstants
import android.view.View
@@ -41,6 +40,7 @@ import com.android.app.animation.Interpolators
import com.android.app.tracing.coroutines.launch
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD
+import com.android.keyguard.AuthInteractionProperties
import com.android.systemui.Flags.msdlFeedback
import com.android.systemui.Flags.newAodTransition
import com.android.systemui.common.shared.model.Icon
@@ -82,7 +82,6 @@ import com.android.systemui.util.ui.isAnimating
import com.android.systemui.util.ui.stopAnimating
import com.android.systemui.util.ui.value
import com.google.android.msdl.data.model.MSDLToken
-import com.google.android.msdl.domain.InteractionProperties
import com.google.android.msdl.domain.MSDLPlayer
import kotlin.math.min
import kotlinx.coroutines.CoroutineDispatcher
@@ -358,14 +357,10 @@ object KeyguardRootViewBinder {
launch {
deviceEntryHapticsInteractor.playSuccessHaptic.collect {
if (msdlFeedback()) {
- val properties =
- object : InteractionProperties {
- override val vibrationAttributes: VibrationAttributes =
- VibrationAttributes.createForUsage(
- VibrationAttributes.USAGE_HARDWARE_FEEDBACK
- )
- }
- msdlPlayer?.playToken(MSDLToken.UNLOCK, properties)
+ msdlPlayer?.playToken(
+ MSDLToken.UNLOCK,
+ authInteractionProperties
+ )
} else {
vibratorHelper.performHapticFeedback(
view,
@@ -378,14 +373,10 @@ object KeyguardRootViewBinder {
launch {
deviceEntryHapticsInteractor.playErrorHaptic.collect {
if (msdlFeedback()) {
- val properties =
- object : InteractionProperties {
- override val vibrationAttributes: VibrationAttributes =
- VibrationAttributes.createForUsage(
- VibrationAttributes.USAGE_HARDWARE_FEEDBACK
- )
- }
- msdlPlayer?.playToken(MSDLToken.FAILURE, properties)
+ msdlPlayer?.playToken(
+ MSDLToken.FAILURE,
+ authInteractionProperties
+ )
} else {
vibratorHelper.performHapticFeedback(
view,
@@ -660,6 +651,7 @@ object KeyguardRootViewBinder {
private val lockIcon = R.id.lock_icon_view
private val deviceEntryIcon = R.id.device_entry_icon_view
private val nsslPlaceholderId = R.id.nssl_placeholder
+ private val authInteractionProperties = AuthInteractionProperties()
private const val ID = "occluding_app_device_entry_unlock_msg"
private const val AOD_ICONS_APPEAR_DURATION: Long = 200
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
index 9f6821051757..a021de446911 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DeviceEntryBackgroundViewModel.kt
@@ -43,23 +43,22 @@ constructor(
val deviceEntryIconViewModel: DeviceEntryIconViewModel,
keyguardTransitionInteractor: KeyguardTransitionInteractor,
configurationInteractor: ConfigurationInteractor,
- lockscreenToAodTransitionViewModel: LockscreenToAodTransitionViewModel,
+ alternateBouncerToAodTransitionViewModel: AlternateBouncerToAodTransitionViewModel,
+ alternateBouncerToDozingTransitionViewModel: AlternateBouncerToDozingTransitionViewModel,
aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
+ dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel,
+ dreamingToAodTransitionViewModel: DreamingToAodTransitionViewModel,
+ dreamingToLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel,
goneToAodTransitionViewModel: GoneToAodTransitionViewModel,
- primaryBouncerToAodTransitionViewModel: PrimaryBouncerToAodTransitionViewModel,
+ goneToDozingTransitionViewModel: GoneToDozingTransitionViewModel,
+ goneToLockscreenTransitionViewModel: GoneToLockscreenTransitionViewModel,
+ lockscreenToAodTransitionViewModel: LockscreenToAodTransitionViewModel,
occludedToAodTransitionViewModel: OccludedToAodTransitionViewModel,
+ occludedToDozingTransitionViewModel: OccludedToDozingTransitionViewModel,
occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel,
- dreamingToLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel,
- alternateBouncerToAodTransitionViewModel: AlternateBouncerToAodTransitionViewModel,
- goneToLockscreenTransitionViewModel: GoneToLockscreenTransitionViewModel,
- goneToDozingTransitionViewModel: GoneToDozingTransitionViewModel,
+ primaryBouncerToAodTransitionViewModel: PrimaryBouncerToAodTransitionViewModel,
primaryBouncerToDozingTransitionViewModel: PrimaryBouncerToDozingTransitionViewModel,
- lockscreenToDozingTransitionViewModel: LockscreenToDozingTransitionViewModel,
- dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel,
- alternateBouncerToDozingTransitionViewModel: AlternateBouncerToDozingTransitionViewModel,
- dreamingToAodTransitionViewModel: DreamingToAodTransitionViewModel,
primaryBouncerToLockscreenTransitionViewModel: PrimaryBouncerToLockscreenTransitionViewModel,
- occludedToDozingTransitionViewModel: OccludedToDozingTransitionViewModel,
) {
val color: Flow<Int> =
deviceEntryIconViewModel.useBackgroundProtection.flatMapLatest { useBackground ->
@@ -98,7 +97,6 @@ constructor(
goneToLockscreenTransitionViewModel.deviceEntryBackgroundViewAlpha,
goneToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
primaryBouncerToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
- lockscreenToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
dozingToLockscreenTransitionViewModel.deviceEntryBackgroundViewAlpha,
alternateBouncerToDozingTransitionViewModel.deviceEntryBackgroundViewAlpha,
dreamingToAodTransitionViewModel.deviceEntryBackgroundViewAlpha,
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
index 27a1f7afb4e1..d3eefca67037 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenToDozingTransitionViewModel.kt
@@ -45,13 +45,7 @@ constructor(
edge = Edge.create(from = LOCKSCREEN, to = DOZING),
)
- val lockscreenAlpha: Flow<Float> =
- transitionAnimation.sharedFlow(
- duration = 250.milliseconds,
- onStep = { 1 - it },
- onFinish = { 1f },
- onCancel = { 1f },
- )
+ val lockscreenAlpha: Flow<Float> = transitionAnimation.immediatelyTransitionTo(1f)
val shortcutsAlpha: Flow<Float> =
transitionAnimation.sharedFlow(
@@ -61,18 +55,16 @@ constructor(
onCancel = { 1f },
)
- val deviceEntryBackgroundViewAlpha: Flow<Float> =
- transitionAnimation.immediatelyTransitionTo(0f)
-
override val deviceEntryParentViewAlpha: Flow<Float> =
deviceEntryUdfpsInteractor.isUdfpsEnrolledAndEnabled.flatMapLatest {
isUdfpsEnrolledAndEnabled ->
- transitionAnimation.immediatelyTransitionTo(
- if (isUdfpsEnrolledAndEnabled) {
- 1f
- } else {
- 0f
- }
- )
+ if (isUdfpsEnrolledAndEnabled) {
+ transitionAnimation.immediatelyTransitionTo(1f)
+ } else {
+ transitionAnimation.sharedFlow(
+ duration = 250.milliseconds,
+ onStep = { 1f - it },
+ )
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt
index 2819e617629d..dd47678e5b36 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenUserActionsViewModel.kt
@@ -28,7 +28,7 @@ import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.util.kotlin.filterValuesNotNull
@@ -40,13 +40,13 @@ import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
/** Models UI state and handles user input for the lockscreen scene. */
-class LockscreenSceneActionsViewModel
+class LockscreenUserActionsViewModel
@AssistedInject
constructor(
private val deviceEntryInteractor: DeviceEntryInteractor,
private val communalInteractor: CommunalInteractor,
private val shadeInteractor: ShadeInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
shadeInteractor.isShadeTouchable
@@ -119,6 +119,6 @@ constructor(
@AssistedFactory
interface Factory {
- fun create(): LockscreenSceneActionsViewModel
+ fun create(): LockscreenUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
index a65243dfe315..d4af1b546369 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/util/MediaFlags.kt
@@ -29,9 +29,8 @@ class MediaFlags @Inject constructor(private val featureFlags: FeatureFlagsClass
* Check whether media control actions should be based on PlaybackState instead of notification
*/
fun areMediaSessionActionsEnabled(packageName: String, user: UserHandle): Boolean {
- val enabled = StatusBarManager.useMediaSessionActionsForApp(packageName, user)
// Allow global override with flag
- return enabled || featureFlags.isEnabled(Flags.MEDIA_SESSION_ACTIONS)
+ return StatusBarManager.useMediaSessionActionsForApp(packageName, user)
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
index 6ef83e262ac8..b6868c172a9f 100644
--- a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeOverlayActionsViewModel.kt
@@ -21,13 +21,13 @@ import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.scene.shared.model.Overlays
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
/** Models the UI state for the user actions for navigating to other scenes or overlays. */
class NotificationsShadeOverlayActionsViewModel @AssistedInject constructor() :
- SceneActionsViewModel() {
+ UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
setActions(
diff --git a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
index 572a0caf49f2..a5c07bc2fdbf 100644
--- a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeUserActionsViewModel.kt
@@ -21,15 +21,15 @@ import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.scene.shared.model.SceneFamilies
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
/**
* Models the UI state for the user actions that the user can perform to navigate to other scenes.
*/
-class NotificationsShadeSceneActionsViewModel @AssistedInject constructor() :
- SceneActionsViewModel() {
+class NotificationsShadeUserActionsViewModel @AssistedInject constructor() :
+ UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
setActions(
@@ -42,6 +42,6 @@ class NotificationsShadeSceneActionsViewModel @AssistedInject constructor() :
@AssistedFactory
interface Factory {
- fun create(): NotificationsShadeSceneActionsViewModel
+ fun create(): NotificationsShadeUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt
index a264f5142293..f77386dbe91b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneContentViewModel.kt
@@ -39,7 +39,7 @@ import kotlinx.coroutines.launch
/**
* Models UI state needed for rendering the content of the quick settings scene.
*
- * Different from [QuickSettingsSceneActionsViewModel] that models the UI state needed to figure out
+ * Different from [QuickSettingsUserActionsViewModel] that models the UI state needed to figure out
* which user actions can trigger navigation to other scenes.
*/
class QuickSettingsSceneContentViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
index 9538392b845f..61c4c8c0de86 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeOverlayActionsViewModel.kt
@@ -21,13 +21,13 @@ import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.scene.shared.model.Overlays
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
/** Models the UI state for the user actions for navigating to other scenes or overlays. */
class QuickSettingsShadeOverlayActionsViewModel @AssistedInject constructor() :
- SceneActionsViewModel() {
+ UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
setActions(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt
index 518582843401..d01b33b7be59 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneContentViewModel.kt
@@ -22,7 +22,7 @@ import dagger.assisted.AssistedInject
/**
* Models UI state used to render the content of the quick settings shade scene.
*
- * Different from [QuickSettingsShadeSceneActionsViewModel], which only models user actions that can
+ * Different from [QuickSettingsShadeUserActionsViewModel], which only models user actions that can
* be performed to navigate to other scenes.
*/
class QuickSettingsShadeSceneContentViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
index 9690aabdba81..d3dc302d44ca 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModel.kt
@@ -21,7 +21,7 @@ import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.UserAction
import com.android.compose.animation.scene.UserActionResult
import com.android.systemui.scene.shared.model.SceneFamilies
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.map
@@ -32,11 +32,11 @@ import kotlinx.coroutines.flow.map
* Different from the [QuickSettingsShadeSceneContentViewModel] which models the _content_ of the
* scene.
*/
-class QuickSettingsShadeSceneActionsViewModel
+class QuickSettingsShadeUserActionsViewModel
@AssistedInject
constructor(
val quickSettingsContainerViewModel: QuickSettingsContainerViewModel,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
quickSettingsContainerViewModel.editModeViewModel.isEditing
@@ -53,6 +53,6 @@ constructor(
@AssistedFactory
interface Factory {
- fun create(): QuickSettingsShadeSceneActionsViewModel
+ fun create(): QuickSettingsShadeUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModel.kt
index 2bb5dc66bc16..54e5caca107c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsUserActionsViewModel.kt
@@ -27,7 +27,7 @@ import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.scene.domain.interactor.SceneBackInteractor
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.Flow
@@ -42,12 +42,12 @@ import kotlinx.coroutines.flow.map
* Different from [QuickSettingsSceneContentViewModel] that models UI state needed for rendering the
* content of the quick settings scene.
*/
-class QuickSettingsSceneActionsViewModel
+class QuickSettingsUserActionsViewModel
@AssistedInject
constructor(
private val qsSceneAdapter: QSSceneAdapter,
sceneBackInteractor: SceneBackInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
private val backScene: Flow<SceneKey> =
sceneBackInteractor.backScene
@@ -82,6 +82,6 @@ constructor(
@AssistedFactory
interface Factory {
- fun create(): QuickSettingsSceneActionsViewModel
+ fun create(): QuickSettingsUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt
index fcf628872e81..115d664c4ccd 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/Scenes.kt
@@ -72,9 +72,7 @@ object Scenes {
* and one for quick settings, [NotificationsShade] and [QuickSettingsShade] scenes are used
* respectively.
*/
- @Deprecated("The quick settings shade scene has been replaced by an overlay")
- @JvmField
- val QuickSettings = SceneKey("quick_settings")
+ @JvmField val QuickSettings = SceneKey("quick_settings")
/**
* The quick settings shade scene shows the quick setting tiles as an overlay UI.
@@ -87,7 +85,9 @@ object Scenes {
* large screens or unfolded foldables, where notifications and quick settings are shown
* side-by-side in their own columns).
*/
- @JvmField val QuickSettingsShade = SceneKey("quick_settings_shade")
+ @Deprecated("The quick settings shade scene has been replaced by an overlay")
+ @JvmField
+ val QuickSettingsShade = SceneKey("quick_settings_shade")
/**
* The shade is the scene that shows a scrollable list of notifications and the minimized
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModel.kt
index 7b0e7f4ded58..ea4122a563ab 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneUserActionsViewModel.kt
@@ -29,11 +29,11 @@ import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.map
-class GoneSceneActionsViewModel
+class GoneUserActionsViewModel
@AssistedInject
constructor(
private val shadeInteractor: ShadeInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
shadeInteractor.shadeMode
@@ -69,6 +69,6 @@ constructor(
@AssistedFactory
interface Factory {
- fun create(): GoneSceneActionsViewModel
+ fun create(): GoneUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModel.kt
index 076613005959..57628d0f3f40 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/UserActionsViewModel.kt
@@ -25,15 +25,13 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/**
- * Base class for view-models that need to keep a map of scene actions (also known as "destination
- * scenes") up-to-date.
+ * Base class for view-models that need to keep a map of user actions up-to-date.
*
* Subclasses need only to override [hydrateActions], suspending forever if they need; they don't
* need to worry about resetting the value of [actions] when the view-model is deactivated/canceled,
* this base class takes care of it.
*/
-// TODO(b/363206563): Rename to UserActionsViewModel.
-abstract class SceneActionsViewModel : ExclusiveActivatable() {
+abstract class UserActionsViewModel : ExclusiveActivatable() {
private val _actions = MutableStateFlow<Map<UserAction, UserActionResult>>(emptyMap())
/**
diff --git a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
index 3bb494b7deca..7fa9926ea920 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/GlanceableHubContainerController.kt
@@ -96,7 +96,7 @@ constructor(
private val lockscreenSmartspaceController: LockscreenSmartspaceController,
@CommunalTouchLog logBuffer: LogBuffer,
) : LifecycleOwner {
- private val logger = Logger(logBuffer, "GlanceableHubContainerController")
+ private val logger = Logger(logBuffer, TAG)
private class CommunalWrapper(context: Context) : FrameLayout(context) {
private val consumers: MutableSet<Consumer<Boolean>> = ArraySet()
@@ -301,7 +301,7 @@ constructor(
if (touchMonitor == null) {
touchMonitor =
- ambientTouchComponentFactory.create(this, HashSet()).getTouchMonitor().apply {
+ ambientTouchComponentFactory.create(this, HashSet(), TAG).getTouchMonitor().apply {
init()
}
}
@@ -508,6 +508,11 @@ constructor(
fun onTouchEvent(ev: MotionEvent): Boolean {
SceneContainerFlag.assertInLegacyMode()
+ if (communalContainerView == null) {
+ // Return early so we don't log unnecessarily and fill up our LogBuffer.
+ return false
+ }
+
// In the case that we are handling full swipes on the lockscreen, are on the lockscreen,
// and the touch is within the horizontal notification band on the screen, do not process
// the touch.
@@ -528,7 +533,7 @@ constructor(
return false
}
- return communalContainerView?.let { handleTouchEventOnCommunalView(ev) } ?: false
+ return handleTouchEventOnCommunalView(ev)
}
private fun handleTouchEventOnCommunalView(ev: MotionEvent): Boolean {
@@ -630,4 +635,8 @@ constructor(
override val lifecycle: Lifecycle
get() = lifecycleRegistry
+
+ companion object {
+ private const val TAG = "GlanceableHubContainer"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
index 7c707592f5ab..ce4c081358ba 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneContentViewModel.kt
@@ -43,7 +43,7 @@ import kotlinx.coroutines.flow.asStateFlow
/**
* Models UI state used to render the content of the shade scene.
*
- * Different from [ShadeSceneActionsViewModel], which only models user actions that can be performed
+ * Different from [ShadeUserActionsViewModel], which only models user actions that can be performed
* to navigate to other scenes.
*/
class ShadeSceneContentViewModel
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt
index ab719132b93e..f8a850a357f1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModel.kt
@@ -24,7 +24,7 @@ import com.android.systemui.qs.ui.adapter.QSSceneAdapter
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
-import com.android.systemui.scene.ui.viewmodel.SceneActionsViewModel
+import com.android.systemui.scene.ui.viewmodel.UserActionsViewModel
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import dagger.assisted.AssistedFactory
@@ -36,12 +36,12 @@ import kotlinx.coroutines.flow.combine
*
* Different from the [ShadeSceneContentViewModel] which models the _content_ of the scene.
*/
-class ShadeSceneActionsViewModel
+class ShadeUserActionsViewModel
@AssistedInject
constructor(
private val qsSceneAdapter: QSSceneAdapter,
private val shadeInteractor: ShadeInteractor,
-) : SceneActionsViewModel() {
+) : UserActionsViewModel() {
override suspend fun hydrateActions(setActions: (Map<UserAction, UserActionResult>) -> Unit) {
combine(
@@ -71,6 +71,6 @@ constructor(
@AssistedFactory
interface Factory {
- fun create(): ShadeSceneActionsViewModel
+ fun create(): ShadeUserActionsViewModel
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt b/packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt
index 922560f16dce..0e1bf728ca46 100644
--- a/packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/smartspace/config/BcSmartspaceConfigProvider.kt
@@ -16,6 +16,7 @@
package com.android.systemui.smartspace.config
+import com.android.systemui.Flags.smartspaceViewpager2
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.plugins.BcSmartspaceConfigPlugin
@@ -23,4 +24,7 @@ class BcSmartspaceConfigProvider(private val featureFlags: FeatureFlags) :
BcSmartspaceConfigPlugin {
override val isDefaultDateWeatherDisabled: Boolean
get() = true
+
+ override val isViewPager2Enabled: Boolean
+ get() = smartspaceViewpager2()
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
new file mode 100644
index 000000000000..3b1e565e122b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/binder/OngoingActivityChipBinder.kt
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.chips.ui.binder
+
+import android.annotation.IdRes
+import android.content.res.ColorStateList
+import android.graphics.drawable.GradientDrawable
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import android.widget.ImageView
+import android.widget.TextView
+import com.android.systemui.common.ui.binder.IconViewBinder
+import com.android.systemui.res.R
+import com.android.systemui.statusbar.StatusBarIconView
+import com.android.systemui.statusbar.chips.ron.shared.StatusBarRonChips
+import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
+import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
+import com.android.systemui.statusbar.chips.ui.view.ChipChronometer
+
+/** Binder for ongoing activity chip views. */
+object OngoingActivityChipBinder {
+ /** Binds the given [chipModel] data to the given [chipView]. */
+ fun bind(chipModel: OngoingActivityChipModel, chipView: View) {
+ val chipContext = chipView.context
+ val chipDefaultIconView: ImageView =
+ chipView.requireViewById(R.id.ongoing_activity_chip_icon)
+ val chipTimeView: ChipChronometer =
+ chipView.requireViewById(R.id.ongoing_activity_chip_time)
+ val chipTextView: TextView = chipView.requireViewById(R.id.ongoing_activity_chip_text)
+ val chipBackgroundView: ChipBackgroundContainer =
+ chipView.requireViewById(R.id.ongoing_activity_chip_background)
+
+ when (chipModel) {
+ is OngoingActivityChipModel.Shown -> {
+ // Data
+ setChipIcon(chipModel, chipBackgroundView, chipDefaultIconView)
+ setChipMainContent(chipModel, chipTextView, chipTimeView)
+ chipView.setOnClickListener(chipModel.onClickListener)
+ updateChipPadding(
+ chipModel,
+ chipBackgroundView,
+ chipTextView,
+ chipTimeView,
+ )
+
+ // Accessibility
+ setChipAccessibility(chipModel, chipView, chipBackgroundView)
+
+ // Colors
+ val textColor = chipModel.colors.text(chipContext)
+ chipTimeView.setTextColor(textColor)
+ chipTextView.setTextColor(textColor)
+ (chipBackgroundView.background as GradientDrawable).color =
+ chipModel.colors.background(chipContext)
+ }
+ is OngoingActivityChipModel.Hidden -> {
+ // The Chronometer should be stopped to prevent leaks -- see b/192243808 and
+ // [Chronometer.start].
+ chipTimeView.stop()
+ }
+ }
+ }
+
+ private fun setChipIcon(
+ chipModel: OngoingActivityChipModel.Shown,
+ backgroundView: ChipBackgroundContainer,
+ defaultIconView: ImageView,
+ ) {
+ // Always remove any previously set custom icon. If we have a new custom icon, we'll re-add
+ // it.
+ backgroundView.removeView(backgroundView.getCustomIconView())
+
+ val iconTint = chipModel.colors.text(defaultIconView.context)
+
+ when (val icon = chipModel.icon) {
+ null -> {
+ defaultIconView.visibility = View.GONE
+ }
+ is OngoingActivityChipModel.ChipIcon.SingleColorIcon -> {
+ IconViewBinder.bind(icon.impl, defaultIconView)
+ defaultIconView.visibility = View.VISIBLE
+ defaultIconView.tintView(iconTint)
+ }
+ is OngoingActivityChipModel.ChipIcon.FullColorAppIcon -> {
+ StatusBarRonChips.assertInNewMode()
+ IconViewBinder.bind(icon.impl, defaultIconView)
+ defaultIconView.visibility = View.VISIBLE
+ defaultIconView.untintView()
+ }
+ is OngoingActivityChipModel.ChipIcon.StatusBarView -> {
+ // Hide the default icon since we'll show this custom icon instead.
+ defaultIconView.visibility = View.GONE
+
+ // Add the new custom icon:
+ // 1. Set up the right visual params.
+ val iconView = icon.impl
+ with(iconView) {
+ id = CUSTOM_ICON_VIEW_ID
+ // TODO(b/354930838): Update the content description to not include "phone" and
+ // maybe include the app name.
+ contentDescription =
+ context.resources.getString(R.string.ongoing_phone_call_content_description)
+ tintView(iconTint)
+ }
+
+ // 2. If we just reinflated the view, we may need to detach the icon view from the
+ // old chip before we reattach it to the new one.
+ // See also: NotificationIconContainerViewBinder#bindIcons.
+ val currentParent = iconView.parent as? ViewGroup
+ if (currentParent != null && currentParent != backgroundView) {
+ currentParent.removeView(iconView)
+ currentParent.removeTransientView(iconView)
+ }
+
+ // 3: Add the icon as the starting view.
+ backgroundView.addView(
+ iconView,
+ /* index= */ 0,
+ generateCustomIconLayoutParams(iconView),
+ )
+ }
+ }
+ }
+
+ private fun View.getCustomIconView(): StatusBarIconView? {
+ return this.findViewById(CUSTOM_ICON_VIEW_ID)
+ }
+
+ private fun ImageView.tintView(color: Int) {
+ this.imageTintList = ColorStateList.valueOf(color)
+ }
+
+ private fun ImageView.untintView() {
+ this.imageTintList = null
+ }
+
+ private fun generateCustomIconLayoutParams(iconView: ImageView): FrameLayout.LayoutParams {
+ val customIconSize =
+ iconView.context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_embedded_padding_icon_size
+ )
+ return FrameLayout.LayoutParams(customIconSize, customIconSize)
+ }
+
+ private fun setChipMainContent(
+ chipModel: OngoingActivityChipModel.Shown,
+ chipTextView: TextView,
+ chipTimeView: ChipChronometer,
+ ) {
+ when (chipModel) {
+ is OngoingActivityChipModel.Shown.Countdown -> {
+ chipTextView.text = chipModel.secondsUntilStarted.toString()
+ chipTextView.visibility = View.VISIBLE
+
+ chipTimeView.hide()
+ }
+ is OngoingActivityChipModel.Shown.Text -> {
+ chipTextView.text = chipModel.text
+ chipTextView.visibility = View.VISIBLE
+
+ chipTimeView.hide()
+ }
+ is OngoingActivityChipModel.Shown.Timer -> {
+ ChipChronometerBinder.bind(chipModel.startTimeMs, chipTimeView)
+ chipTimeView.visibility = View.VISIBLE
+
+ chipTextView.visibility = View.GONE
+ }
+ is OngoingActivityChipModel.Shown.IconOnly -> {
+ chipTextView.visibility = View.GONE
+ chipTimeView.hide()
+ }
+ }
+ }
+
+ private fun ChipChronometer.hide() {
+ // The Chronometer should be stopped to prevent leaks -- see b/192243808 and
+ // [Chronometer.start].
+ this.stop()
+ this.visibility = View.GONE
+ }
+
+ private fun updateChipPadding(
+ chipModel: OngoingActivityChipModel.Shown,
+ backgroundView: View,
+ chipTextView: TextView,
+ chipTimeView: ChipChronometer,
+ ) {
+ if (chipModel.icon != null) {
+ if (chipModel.icon is OngoingActivityChipModel.ChipIcon.StatusBarView) {
+ // If the icon is a custom [StatusBarIconView], then it should've come from
+ // `Notification.smallIcon`, which is required to embed its own paddings. We need to
+ // adjust the other paddings to make everything look good :)
+ backgroundView.setBackgroundPaddingForEmbeddedPaddingIcon()
+ chipTextView.setTextPaddingForEmbeddedPaddingIcon()
+ chipTimeView.setTextPaddingForEmbeddedPaddingIcon()
+ } else {
+ backgroundView.setBackgroundPaddingForNormalIcon()
+ chipTextView.setTextPaddingForNormalIcon()
+ chipTimeView.setTextPaddingForNormalIcon()
+ }
+ } else {
+ backgroundView.setBackgroundPaddingForNoIcon()
+ chipTextView.setTextPaddingForNoIcon()
+ chipTimeView.setTextPaddingForNoIcon()
+ }
+ }
+
+ private fun View.setTextPaddingForEmbeddedPaddingIcon() {
+ val newPaddingEnd =
+ context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_text_end_padding_for_embedded_padding_icon
+ )
+ setPaddingRelative(
+ // The icon should embed enough padding between the icon and time view.
+ /* start= */ 0,
+ this.paddingTop,
+ newPaddingEnd,
+ this.paddingBottom,
+ )
+ }
+
+ private fun View.setTextPaddingForNormalIcon() {
+ this.setPaddingRelative(
+ this.context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_icon_text_padding
+ ),
+ paddingTop,
+ // The background view will contain the right end padding.
+ /* end= */ 0,
+ paddingBottom,
+ )
+ }
+
+ private fun View.setTextPaddingForNoIcon() {
+ // The background view will have even start & end paddings, so we don't want the text view
+ // to add any additional padding.
+ this.setPaddingRelative(/* start= */ 0, paddingTop, /* end= */ 0, paddingBottom)
+ }
+
+ private fun View.setBackgroundPaddingForEmbeddedPaddingIcon() {
+ val sidePadding =
+ context.resources.getDimensionPixelSize(
+ R.dimen.ongoing_activity_chip_side_padding_for_embedded_padding_icon
+ )
+ setPaddingRelative(
+ sidePadding,
+ paddingTop,
+ sidePadding,
+ paddingBottom,
+ )
+ }
+
+ private fun View.setBackgroundPaddingForNormalIcon() {
+ val sidePadding =
+ context.resources.getDimensionPixelSize(R.dimen.ongoing_activity_chip_side_padding)
+ setPaddingRelative(
+ sidePadding,
+ paddingTop,
+ sidePadding,
+ paddingBottom,
+ )
+ }
+
+ private fun View.setBackgroundPaddingForNoIcon() {
+ // The padding for the normal icon is also appropriate for no icon.
+ setBackgroundPaddingForNormalIcon()
+ }
+
+ private fun setChipAccessibility(
+ chipModel: OngoingActivityChipModel.Shown,
+ chipView: View,
+ chipBackgroundView: View,
+ ) {
+ when (chipModel) {
+ is OngoingActivityChipModel.Shown.Countdown -> {
+ // Set as assertive so talkback will announce the countdown
+ chipView.accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE
+ }
+ is OngoingActivityChipModel.Shown.Timer,
+ is OngoingActivityChipModel.Shown.Text,
+ is OngoingActivityChipModel.Shown.IconOnly -> {
+ chipView.accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE
+ }
+ }
+ // Clickable chips need to be a minimum size for accessibility purposes, but let
+ // non-clickable chips be smaller.
+ if (chipModel.onClickListener != null) {
+ chipBackgroundView.minimumWidth =
+ chipBackgroundView.context.resources.getDimensionPixelSize(
+ R.dimen.min_clickable_item_size
+ )
+ } else {
+ chipBackgroundView.minimumWidth = 0
+ }
+ }
+
+ @IdRes private val CUSTOM_ICON_VIEW_ID = R.id.ongoing_activity_chip_custom_icon
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt
index 04c4516c9bed..199eb0613a0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt
@@ -151,13 +151,13 @@ constructor(
}
/**
- * A flow modeling the chip that should be shown in the status bar after accounting for possibly
- * multiple ongoing activities and animation requirements.
+ * A flow modeling the primary chip that should be shown in the status bar after accounting for
+ * possibly multiple ongoing activities and animation requirements.
*
* [com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment] is responsible for
* actually displaying the chip.
*/
- val chip: StateFlow<OngoingActivityChipModel> =
+ val primaryChip: StateFlow<OngoingActivityChipModel> =
internalChip
.pairwise(initialValue = DEFAULT_INTERNAL_HIDDEN_MODEL)
.map { (old, new) ->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
index 3a2f95e5ebc4..6d0148a24cf8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/VisualStabilityCoordinator.java
@@ -22,7 +22,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.android.systemui.Dumpable;
-import com.android.systemui.communal.domain.interactor.CommunalInteractor;
+import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dump.DumpManager;
@@ -32,6 +32,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.shade.domain.interactor.ShadeAnimationInteractor;
+import com.android.systemui.shade.domain.interactor.ShadeInteractor;
import com.android.systemui.statusbar.notification.VisibilityLocationProvider;
import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry;
@@ -43,6 +44,7 @@ import com.android.systemui.statusbar.notification.domain.interactor.SeenNotific
import com.android.systemui.statusbar.notification.shared.NotificationMinimalismPrototype;
import com.android.systemui.statusbar.policy.HeadsUpManager;
import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.kotlin.BooleanFlowOperators;
import com.android.systemui.util.kotlin.JavaAdapter;
import java.io.PrintWriter;
@@ -70,7 +72,8 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
private final VisibilityLocationProvider mVisibilityLocationProvider;
private final VisualStabilityProvider mVisualStabilityProvider;
private final WakefulnessLifecycle mWakefulnessLifecycle;
- private final CommunalInteractor mCommunalInteractor;
+ private final CommunalSceneInteractor mCommunalSceneInteractor;
+ private final ShadeInteractor mShadeInteractor;
private final KeyguardTransitionInteractor mKeyguardTransitionInteractor;
private final VisualStabilityCoordinatorLogger mLogger;
@@ -110,7 +113,8 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
VisibilityLocationProvider visibilityLocationProvider,
VisualStabilityProvider visualStabilityProvider,
WakefulnessLifecycle wakefulnessLifecycle,
- CommunalInteractor communalInteractor,
+ CommunalSceneInteractor communalSceneInteractor,
+ ShadeInteractor shadeInteractor,
KeyguardTransitionInteractor keyguardTransitionInteractor,
VisualStabilityCoordinatorLogger logger) {
mHeadsUpManager = headsUpManager;
@@ -122,7 +126,8 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
mWakefulnessLifecycle = wakefulnessLifecycle;
mStatusBarStateController = statusBarStateController;
mDelayableExecutor = delayableExecutor;
- mCommunalInteractor = communalInteractor;
+ mCommunalSceneInteractor = communalSceneInteractor;
+ mShadeInteractor = shadeInteractor;
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
mLogger = logger;
@@ -141,7 +146,11 @@ public class VisualStabilityCoordinator implements Coordinator, Dumpable {
this::onShadeOrQsClosingChanged);
mJavaAdapter.alwaysCollectFlow(mShadeAnimationInteractor.isLaunchingActivity(),
this::onLaunchingActivityChanged);
- mJavaAdapter.alwaysCollectFlow(mCommunalInteractor.isIdleOnCommunal(),
+ mJavaAdapter.alwaysCollectFlow(
+ BooleanFlowOperators.INSTANCE.allOf(
+ mCommunalSceneInteractor.isIdleOnCommunal(),
+ BooleanFlowOperators.INSTANCE.not(mShadeInteractor.isAnyFullyExpanded())
+ ),
this::onCommunalShowingChanged);
if (SceneContainerFlag.isEnabled()) {
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 b9628e95c436..48e69893cd7b 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
@@ -3710,7 +3710,7 @@ public class NotificationStackScrollLayout
if (!isScrollingEnabled()) {
return false;
}
- if (isInsideQsHeader(ev) && !mIsBeingDragged) {
+ if (!isInScrollableRegion(ev) && !mIsBeingDragged) {
return false;
}
mForcedScroll = null;
@@ -3878,11 +3878,26 @@ public class NotificationStackScrollLayout
return mFlingAfterUpEvent;
}
- protected boolean isInsideQsHeader(MotionEvent ev) {
- if (SceneContainerFlag.isEnabled()) {
- return ev.getY() < mAmbientState.getStackTop();
+ /** Is this touch event inside the scrollable region? */
+ @VisibleForTesting
+ boolean isInScrollableRegion(MotionEvent ev) {
+ if (!SceneContainerFlag.isEnabled()) {
+ return !isInsideQsHeader(ev);
+ }
+ ShadeScrimShape shape = mScrollViewFields.getScrimClippingShape();
+ if (shape == null) {
+ return true; // When there is no scrim, consider this event scrollable.
}
+ ShadeScrimBounds bounds = shape.getBounds();
+ return ev.getX() >= bounds.getLeft()
+ && ev.getX() <= bounds.getRight()
+ && ev.getY() >= bounds.getTop()
+ && ev.getY() <= bounds.getBottom();
+ }
+
+ protected boolean isInsideQsHeader(MotionEvent ev) {
+ SceneContainerFlag.assertInLegacyMode();
if (QSComposeFragment.isEnabled()) {
if (mQSHeaderBoundsProvider == null) {
return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index c3da7fcc86c8..178c31839154 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -435,13 +435,14 @@ public class KeyguardStatusBarView extends RelativeLayout {
/** Should only be called from {@link KeyguardStatusBarViewController}. */
void onOverlayChanged() {
- int theme = Utils.getThemeAttr(mContext, com.android.internal.R.attr.textAppearanceSmall);
- mCarrierLabel.setTextAppearance(theme);
+ final int carrierTheme = R.style.TextAppearance_StatusBar_Clock;
+ mCarrierLabel.setTextAppearance(carrierTheme);
mBatteryView.updatePercentView();
+ final int userSwitcherTheme = R.style.TextAppearance_StatusBar_UserChip;
TextView userSwitcherName = mUserSwitcherContainer.findViewById(R.id.current_user_name);
if (userSwitcherName != null) {
- userSwitcherName.setTextAppearance(theme);
+ userSwitcherName.setTextAppearance(userSwitcherTheme);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
index 5be4ba222174..4a0fdeebe82b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java
@@ -121,7 +121,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
private MultiSourceMinAlphaController mEndSideAlphaController;
private LinearLayout mEndSideContent;
private View mClockView;
- private View mOngoingActivityChip;
+ private View mPrimaryOngoingActivityChip;
private View mNotificationIconAreaInner;
// Visibilities come in from external system callers via disable flags, but we also sometimes
// modify the visibilities internally. We need to store both so that we don't accidentally
@@ -354,7 +354,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
mEndSideContent = mStatusBar.findViewById(R.id.status_bar_end_side_content);
mEndSideAlphaController = new MultiSourceMinAlphaController(mEndSideContent);
mClockView = mStatusBar.findViewById(R.id.clock);
- mOngoingActivityChip = mStatusBar.findViewById(R.id.ongoing_activity_chip);
+ mPrimaryOngoingActivityChip = mStatusBar.findViewById(R.id.ongoing_activity_chip_primary);
showEndSideContent(false);
showClock(false);
initOperatorName();
@@ -636,9 +636,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
// icons so if the icons are disabled then the activity chip should be, too.)
boolean showOngoingActivityChip = hasOngoingActivity && !disableNotifications;
if (showOngoingActivityChip) {
- showOngoingActivityChip(animate);
+ showPrimaryOngoingActivityChip(animate);
} else {
- hideOngoingActivityChip(animate);
+ hidePrimaryOngoingActivityChip(animate);
}
}
@@ -729,20 +729,20 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
animateShow(mClockView, animate);
}
- /** Hides the ongoing activity chip. */
- private void hideOngoingActivityChip(boolean animate) {
- animateHiddenState(mOngoingActivityChip, View.GONE, animate);
+ /** Hides the primary ongoing activity chip. */
+ private void hidePrimaryOngoingActivityChip(boolean animate) {
+ animateHiddenState(mPrimaryOngoingActivityChip, View.GONE, animate);
}
/**
- * Displays the ongoing activity chip.
+ * Displays the primary ongoing activity chip.
*
* If Flags.statusBarScreenSharingChips is disabled, this chip will only ever contain the
* ongoing call information, If that flag is enabled, it will support different kinds of ongoing
* activities. See b/332662551.
*/
- private void showOngoingActivityChip(boolean animate) {
- animateShow(mOngoingActivityChip, animate);
+ private void showPrimaryOngoingActivityChip(boolean animate) {
+ animateShow(mPrimaryOngoingActivityChip, animate);
}
/**
@@ -850,7 +850,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue
private void initOngoingCallChip() {
mOngoingCallController.addCallback(mOngoingCallListener);
- mOngoingCallController.setChipView(mOngoingActivityChip);
+ mOngoingCallController.setChipView(mPrimaryOngoingActivityChip);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
index c24d69465043..87d0e6420128 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/binder/CollapsedStatusBarViewBinder.kt
@@ -18,28 +18,16 @@ package com.android.systemui.statusbar.pipeline.shared.ui.binder
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
-import android.annotation.IdRes
-import android.content.res.ColorStateList
-import android.graphics.drawable.GradientDrawable
import android.view.View
-import android.view.ViewGroup
-import android.widget.FrameLayout
-import android.widget.ImageView
-import android.widget.TextView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.systemui.Flags
-import com.android.systemui.common.ui.binder.IconViewBinder
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.res.R
import com.android.systemui.scene.shared.flag.SceneContainerFlag
-import com.android.systemui.statusbar.StatusBarIconView
-import com.android.systemui.statusbar.chips.ron.shared.StatusBarRonChips
-import com.android.systemui.statusbar.chips.ui.binder.ChipChronometerBinder
+import com.android.systemui.statusbar.chips.ui.binder.OngoingActivityChipBinder
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
-import com.android.systemui.statusbar.chips.ui.view.ChipBackgroundContainer
-import com.android.systemui.statusbar.chips.ui.view.ChipChronometer
import com.android.systemui.statusbar.notification.shared.NotificationsLiveDataStoreRefactor
import com.android.systemui.statusbar.pipeline.shared.ui.viewmodel.CollapsedStatusBarViewModel
import javax.inject.Inject
@@ -93,58 +81,22 @@ class CollapsedStatusBarViewBinderImpl @Inject constructor() : CollapsedStatusBa
}
if (Flags.statusBarScreenSharingChips()) {
- val chipView: View = view.requireViewById(R.id.ongoing_activity_chip)
- val chipContext = chipView.context
- val chipDefaultIconView: ImageView =
- chipView.requireViewById(R.id.ongoing_activity_chip_icon)
- val chipTimeView: ChipChronometer =
- chipView.requireViewById(R.id.ongoing_activity_chip_time)
- val chipTextView: TextView =
- chipView.requireViewById(R.id.ongoing_activity_chip_text)
- val chipBackgroundView =
- chipView.requireViewById<ChipBackgroundContainer>(
- R.id.ongoing_activity_chip_background
- )
+ val primaryChipView: View =
+ view.requireViewById(R.id.ongoing_activity_chip_primary)
launch {
- viewModel.ongoingActivityChip.collect { chipModel ->
- when (chipModel) {
- is OngoingActivityChipModel.Shown -> {
- // Data
- setChipIcon(chipModel, chipBackgroundView, chipDefaultIconView)
- setChipMainContent(chipModel, chipTextView, chipTimeView)
- chipView.setOnClickListener(chipModel.onClickListener)
- updateChipPadding(
- chipModel,
- chipBackgroundView,
- chipTextView,
- chipTimeView,
- )
-
- // Accessibility
- setChipAccessibility(chipModel, chipView, chipBackgroundView)
-
- // Colors
- val textColor = chipModel.colors.text(chipContext)
- chipTimeView.setTextColor(textColor)
- chipTextView.setTextColor(textColor)
- (chipBackgroundView.background as GradientDrawable).color =
- chipModel.colors.background(chipContext)
-
- // Notify listeners
+ viewModel.primaryOngoingActivityChip.collect { primaryChipModel ->
+ OngoingActivityChipBinder.bind(primaryChipModel, primaryChipView)
+ when (primaryChipModel) {
+ is OngoingActivityChipModel.Shown ->
listener.onOngoingActivityStatusChanged(
hasOngoingActivity = true,
shouldAnimate = true,
)
- }
- is OngoingActivityChipModel.Hidden -> {
- // The Chronometer should be stopped to prevent leaks -- see
- // b/192243808 and [Chronometer.start].
- chipTimeView.stop()
+ is OngoingActivityChipModel.Hidden ->
listener.onOngoingActivityStatusChanged(
hasOngoingActivity = false,
- shouldAnimate = chipModel.shouldAnimate,
+ shouldAnimate = primaryChipModel.shouldAnimate,
)
- }
}
}
}
@@ -161,240 +113,6 @@ class CollapsedStatusBarViewBinderImpl @Inject constructor() : CollapsedStatusBa
}
}
- private fun setChipIcon(
- chipModel: OngoingActivityChipModel.Shown,
- backgroundView: ChipBackgroundContainer,
- defaultIconView: ImageView,
- ) {
- // Always remove any previously set custom icon. If we have a new custom icon, we'll re-add
- // it.
- backgroundView.removeView(backgroundView.getCustomIconView())
-
- val iconTint = chipModel.colors.text(defaultIconView.context)
-
- when (val icon = chipModel.icon) {
- null -> {
- defaultIconView.visibility = View.GONE
- }
- is OngoingActivityChipModel.ChipIcon.SingleColorIcon -> {
- IconViewBinder.bind(icon.impl, defaultIconView)
- defaultIconView.visibility = View.VISIBLE
- defaultIconView.tintView(iconTint)
- }
- is OngoingActivityChipModel.ChipIcon.FullColorAppIcon -> {
- StatusBarRonChips.assertInNewMode()
- IconViewBinder.bind(icon.impl, defaultIconView)
- defaultIconView.visibility = View.VISIBLE
- defaultIconView.untintView()
- }
- is OngoingActivityChipModel.ChipIcon.StatusBarView -> {
- // Hide the default icon since we'll show this custom icon instead.
- defaultIconView.visibility = View.GONE
-
- // Add the new custom icon:
- // 1. Set up the right visual params.
- val iconView = icon.impl
- with(iconView) {
- id = CUSTOM_ICON_VIEW_ID
- // TODO(b/354930838): Update the content description to not include "phone" and
- // maybe include the app name.
- contentDescription =
- context.resources.getString(R.string.ongoing_phone_call_content_description)
- tintView(iconTint)
- }
-
- // 2. If we just reinflated the view, we may need to detach the icon view from the
- // old chip before we reattach it to the new one.
- // See also: NotificationIconContainerViewBinder#bindIcons.
- val currentParent = iconView.parent as? ViewGroup
- if (currentParent != null && currentParent != backgroundView) {
- currentParent.removeView(iconView)
- currentParent.removeTransientView(iconView)
- }
-
- // 3: Add the icon as the starting view.
- backgroundView.addView(
- iconView,
- /* index= */ 0,
- generateCustomIconLayoutParams(iconView),
- )
- }
- }
- }
-
- private fun View.getCustomIconView(): StatusBarIconView? {
- return this.findViewById(CUSTOM_ICON_VIEW_ID)
- }
-
- private fun ImageView.tintView(color: Int) {
- this.imageTintList = ColorStateList.valueOf(color)
- }
-
- private fun ImageView.untintView() {
- this.imageTintList = null
- }
-
- private fun generateCustomIconLayoutParams(iconView: ImageView): FrameLayout.LayoutParams {
- val customIconSize =
- iconView.context.resources.getDimensionPixelSize(
- R.dimen.ongoing_activity_chip_embedded_padding_icon_size
- )
- return FrameLayout.LayoutParams(customIconSize, customIconSize)
- }
-
- private fun setChipMainContent(
- chipModel: OngoingActivityChipModel.Shown,
- chipTextView: TextView,
- chipTimeView: ChipChronometer,
- ) {
- when (chipModel) {
- is OngoingActivityChipModel.Shown.Countdown -> {
- chipTextView.text = chipModel.secondsUntilStarted.toString()
- chipTextView.visibility = View.VISIBLE
-
- chipTimeView.hide()
- }
- is OngoingActivityChipModel.Shown.Text -> {
- chipTextView.text = chipModel.text
- chipTextView.visibility = View.VISIBLE
-
- chipTimeView.hide()
- }
- is OngoingActivityChipModel.Shown.Timer -> {
- ChipChronometerBinder.bind(chipModel.startTimeMs, chipTimeView)
- chipTimeView.visibility = View.VISIBLE
-
- chipTextView.visibility = View.GONE
- }
- is OngoingActivityChipModel.Shown.IconOnly -> {
- chipTextView.visibility = View.GONE
- chipTimeView.hide()
- }
- }
- }
-
- private fun ChipChronometer.hide() {
- // The Chronometer should be stopped to prevent leaks -- see b/192243808 and
- // [Chronometer.start].
- this.stop()
- this.visibility = View.GONE
- }
-
- private fun updateChipPadding(
- chipModel: OngoingActivityChipModel.Shown,
- backgroundView: View,
- chipTextView: TextView,
- chipTimeView: ChipChronometer,
- ) {
- if (chipModel.icon != null) {
- if (chipModel.icon is OngoingActivityChipModel.ChipIcon.StatusBarView) {
- // If the icon is a custom [StatusBarIconView], then it should've come from
- // `Notification.smallIcon`, which is required to embed its own paddings. We need to
- // adjust the other paddings to make everything look good :)
- backgroundView.setBackgroundPaddingForEmbeddedPaddingIcon()
- chipTextView.setTextPaddingForEmbeddedPaddingIcon()
- chipTimeView.setTextPaddingForEmbeddedPaddingIcon()
- } else {
- backgroundView.setBackgroundPaddingForNormalIcon()
- chipTextView.setTextPaddingForNormalIcon()
- chipTimeView.setTextPaddingForNormalIcon()
- }
- } else {
- backgroundView.setBackgroundPaddingForNoIcon()
- chipTextView.setTextPaddingForNoIcon()
- chipTimeView.setTextPaddingForNoIcon()
- }
- }
-
- private fun View.setTextPaddingForEmbeddedPaddingIcon() {
- val newPaddingEnd =
- context.resources.getDimensionPixelSize(
- R.dimen.ongoing_activity_chip_text_end_padding_for_embedded_padding_icon
- )
- setPaddingRelative(
- // The icon should embed enough padding between the icon and time view.
- /* start= */ 0,
- this.paddingTop,
- newPaddingEnd,
- this.paddingBottom,
- )
- }
-
- private fun View.setTextPaddingForNormalIcon() {
- this.setPaddingRelative(
- this.context.resources.getDimensionPixelSize(
- R.dimen.ongoing_activity_chip_icon_text_padding
- ),
- paddingTop,
- // The background view will contain the right end padding.
- /* end= */ 0,
- paddingBottom,
- )
- }
-
- private fun View.setTextPaddingForNoIcon() {
- // The background view will have even start & end paddings, so we don't want the text view
- // to add any additional padding.
- this.setPaddingRelative(/* start= */ 0, paddingTop, /* end= */ 0, paddingBottom)
- }
-
- private fun View.setBackgroundPaddingForEmbeddedPaddingIcon() {
- val sidePadding =
- context.resources.getDimensionPixelSize(
- R.dimen.ongoing_activity_chip_side_padding_for_embedded_padding_icon
- )
- setPaddingRelative(
- sidePadding,
- paddingTop,
- sidePadding,
- paddingBottom,
- )
- }
-
- private fun View.setBackgroundPaddingForNormalIcon() {
- val sidePadding =
- context.resources.getDimensionPixelSize(R.dimen.ongoing_activity_chip_side_padding)
- setPaddingRelative(
- sidePadding,
- paddingTop,
- sidePadding,
- paddingBottom,
- )
- }
-
- private fun View.setBackgroundPaddingForNoIcon() {
- // The padding for the normal icon is also appropriate for no icon.
- setBackgroundPaddingForNormalIcon()
- }
-
- private fun setChipAccessibility(
- chipModel: OngoingActivityChipModel.Shown,
- chipView: View,
- chipBackgroundView: View,
- ) {
- when (chipModel) {
- is OngoingActivityChipModel.Shown.Countdown -> {
- // Set as assertive so talkback will announce the countdown
- chipView.accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_ASSERTIVE
- }
- is OngoingActivityChipModel.Shown.Timer,
- is OngoingActivityChipModel.Shown.Text,
- is OngoingActivityChipModel.Shown.IconOnly -> {
- chipView.accessibilityLiveRegion = View.ACCESSIBILITY_LIVE_REGION_NONE
- }
- }
- // Clickable chips need to be a minimum size for accessibility purposes, but let
- // non-clickable chips be smaller.
- if (chipModel.onClickListener != null) {
- chipBackgroundView.minimumWidth =
- chipBackgroundView.context.resources.getDimensionPixelSize(
- R.dimen.min_clickable_item_size
- )
- } else {
- chipBackgroundView.minimumWidth = 0
- }
- }
-
private fun animateLightsOutView(view: View, visible: Boolean) {
view.animate().cancel()
@@ -424,10 +142,6 @@ class CollapsedStatusBarViewBinderImpl @Inject constructor() : CollapsedStatusBa
)
.start()
}
-
- companion object {
- @IdRes private val CUSTOM_ICON_VIEW_ID = R.id.ongoing_activity_chip_custom_icon
- }
}
/** Listener for various events that may affect the status bar's visibility. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
index d6c3834c1bf1..547423156eb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModel.kt
@@ -64,8 +64,11 @@ interface CollapsedStatusBarViewModel {
/** Emits whenever a transition from lockscreen to dream has started. */
val transitionFromLockscreenToDreamStartedEvent: Flow<Unit>
- /** The ongoing activity chip that should be shown on the left-hand side of the status bar. */
- val ongoingActivityChip: StateFlow<OngoingActivityChipModel>
+ /**
+ * The ongoing activity chip that should be primarily shown on the left-hand side of the status
+ * bar. If there are multiple ongoing activity chips, this one should take priority.
+ */
+ val primaryOngoingActivityChip: StateFlow<OngoingActivityChipModel>
/**
* True if the current scene can show the home status bar (aka this status bar), and false if
@@ -108,7 +111,7 @@ constructor(
.filter { it.transitionState == TransitionState.STARTED }
.map {}
- override val ongoingActivityChip = ongoingActivityChipsViewModel.chip
+ override val primaryOngoingActivityChip = ongoingActivityChipsViewModel.primaryChip
override val isHomeStatusBarAllowedByScene: StateFlow<Boolean> =
combine(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
index 885abcafaefc..7df4b2cdb217 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImpl.kt
@@ -29,8 +29,6 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.core.LogLevel
import com.android.systemui.log.table.TableLogBuffer
@@ -75,7 +73,6 @@ import kotlinx.coroutines.flow.stateIn
class WifiRepositoryImpl
@Inject
constructor(
- featureFlags: FeatureFlags,
@Application private val scope: CoroutineScope,
@Main private val mainExecutor: Executor,
@Background private val bgDispatcher: CoroutineDispatcher,
@@ -90,8 +87,6 @@ constructor(
mainExecutor.execute { it.currentState = Lifecycle.State.CREATED }
}
- private val isInstantTetherEnabled = featureFlags.isEnabled(Flags.INSTANT_TETHER)
-
private var wifiPickerTracker: WifiPickerTracker? = null
private val wifiPickerTrackerInfo: StateFlow<WifiPickerTrackerInfo> = run {
@@ -109,16 +104,11 @@ constructor(
val connectedEntry = wifiPickerTracker.mergedOrPrimaryConnection
logOnWifiEntriesChanged(connectedEntry)
+ val activeNetworks = wifiPickerTracker?.activeWifiEntries ?: emptyList()
val secondaryNetworks =
- if (featureFlags.isEnabled(Flags.WIFI_SECONDARY_NETWORKS)) {
- val activeNetworks =
- wifiPickerTracker?.activeWifiEntries ?: emptyList()
- activeNetworks
- .filter { it != connectedEntry && !it.isPrimaryNetwork }
- .map { it.toWifiNetworkModel() }
- } else {
- emptyList()
- }
+ activeNetworks
+ .filter { it != connectedEntry && !it.isPrimaryNetwork }
+ .map { it.toWifiNetworkModel() }
// [WifiPickerTracker.connectedWifiEntry] will return the same instance
// but with updated internals. For example, when its validation status
@@ -130,7 +120,8 @@ constructor(
// into our internal model immediately. [toWifiNetworkModel] always
// returns a new instance, so the flow is guaranteed to emit.
send(
- newPrimaryNetwork = connectedEntry?.toPrimaryWifiNetworkModel()
+ newPrimaryNetwork =
+ connectedEntry?.toPrimaryWifiNetworkModel()
?: WIFI_NETWORK_DEFAULT,
newSecondaryNetworks = secondaryNetworks,
newIsDefault = connectedEntry?.isDefaultNetwork ?: false,
@@ -277,7 +268,7 @@ constructor(
}
val hotspotDeviceType =
- if (isInstantTetherEnabled && this is HotspotNetworkEntry) {
+ if (this is HotspotNetworkEntry) {
this.deviceType.toHotspotDeviceType()
} else {
WifiNetworkModel.HotspotDeviceType.NONE
@@ -408,7 +399,6 @@ constructor(
class Factory
@Inject
constructor(
- private val featureFlags: FeatureFlags,
@Application private val scope: CoroutineScope,
@Main private val mainExecutor: Executor,
@Background private val bgDispatcher: CoroutineDispatcher,
@@ -418,7 +408,6 @@ constructor(
) {
fun create(wifiManager: WifiManager): WifiRepositoryImpl {
return WifiRepositoryImpl(
- featureFlags,
scope,
mainExecutor,
bgDispatcher,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
index 0e88f44e0152..af93880bad51 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ui/dialog/composable/ModeTile.kt
@@ -90,9 +90,11 @@ fun ModeTile(viewModel: ModeTileViewModel) {
viewModel.subtext,
fontWeight = FontWeight.W400,
modifier =
- Modifier.tileMarquee().testTag("state").clearAndSetSemantics {
- contentDescription = viewModel.subtextDescription
- }
+ Modifier.tileMarquee()
+ .testTag(if (viewModel.enabled) "stateOn" else "stateOff")
+ .clearAndSetSemantics {
+ contentDescription = viewModel.subtextDescription
+ }
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index 28effe909521..8934d8f8a954 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -1280,6 +1280,8 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
private final class Receiver extends BroadcastReceiver {
+ private static final int STREAM_UNKNOWN = -1;
+
public void init() {
final IntentFilter filter = new IntentFilter();
filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
@@ -1301,30 +1303,39 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
final String action = intent.getAction();
boolean changed = false;
if (action.equals(AudioManager.VOLUME_CHANGED_ACTION)) {
- final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
+ STREAM_UNKNOWN);
final int level = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE, -1);
final int oldLevel = intent
.getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_VALUE, -1);
if (D.BUG) Log.d(TAG, "onReceive VOLUME_CHANGED_ACTION stream=" + stream
+ " level=" + level + " oldLevel=" + oldLevel);
- changed = updateStreamLevelW(stream, level);
+ if (stream != STREAM_UNKNOWN) {
+ changed = updateStreamLevelW(stream, level);
+ }
} else if (action.equals(AudioManager.STREAM_DEVICES_CHANGED_ACTION)) {
- final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
+ STREAM_UNKNOWN);
final int devices = intent
.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_DEVICES, -1);
final int oldDevices = intent
.getIntExtra(AudioManager.EXTRA_PREV_VOLUME_STREAM_DEVICES, -1);
if (D.BUG) Log.d(TAG, "onReceive STREAM_DEVICES_CHANGED_ACTION stream="
+ stream + " devices=" + devices + " oldDevices=" + oldDevices);
- changed = checkRoutedToBluetoothW(stream);
- changed |= onVolumeChangedW(stream, 0);
+ if (stream != STREAM_UNKNOWN) {
+ changed |= checkRoutedToBluetoothW(stream);
+ changed |= onVolumeChangedW(stream, 0);
+ }
} else if (action.equals(AudioManager.STREAM_MUTE_CHANGED_ACTION)) {
- final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ final int stream = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE,
+ STREAM_UNKNOWN);
final boolean muted = intent
.getBooleanExtra(AudioManager.EXTRA_STREAM_VOLUME_MUTED, false);
if (D.BUG) Log.d(TAG, "onReceive STREAM_MUTE_CHANGED_ACTION stream=" + stream
+ " muted=" + muted);
- changed = updateStreamMuteW(stream, muted);
+ if (stream != STREAM_UNKNOWN) {
+ changed = updateStreamMuteW(stream, muted);
+ }
} else if (action.equals(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED)) {
if (D.BUG) Log.d(TAG, "onReceive ACTION_EFFECTS_SUPPRESSOR_CHANGED");
changed = updateEffectsSuppressorW(mNoMan.getEffectsSuppressor());
diff --git a/packages/SystemUI/tests/Android.bp b/packages/SystemUI/tests/Android.bp
index 88939a2ba67d..f601387d0910 100644
--- a/packages/SystemUI/tests/Android.bp
+++ b/packages/SystemUI/tests/Android.bp
@@ -50,3 +50,14 @@ android_test {
additional_manifests: ["AndroidManifest.xml"],
manifest: "AndroidManifest-base.xml",
}
+
+test_module_config {
+ name: "SystemUITests_systemui_accessibility",
+ base: "SystemUITests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.systemui.accessibility"],
+ exclude_annotations: [
+ "android.platform.test.annotations.Postsubmit",
+ "android.platform.test.annotations.FlakyTest",
+ ],
+}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
index 347605de6616..43a780357027 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/EmergencyButtonControllerTest.kt
@@ -19,6 +19,7 @@ package com.android.keyguard
import android.app.ActivityTaskManager
import android.content.pm.PackageManager
import android.os.PowerManager
+import android.platform.test.annotations.EnableFlags
import android.telecom.TelecomManager
import android.telephony.TelephonyManager
import android.testing.TestableLooper
@@ -26,14 +27,20 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.internal.logging.MetricsLogger
import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
+import com.android.systemui.haptics.msdl.FakeMSDLPlayer
+import com.android.systemui.haptics.msdl.msdlPlayer
import com.android.systemui.shade.ShadeController
import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.testKosmos
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
+import com.google.android.msdl.data.model.MSDLToken
+import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -64,6 +71,8 @@ class EmergencyButtonControllerTest : SysuiTestCase() {
val fakeSystemClock = FakeSystemClock()
val mainExecutor = FakeExecutor(fakeSystemClock)
val backgroundExecutor = FakeExecutor(fakeSystemClock)
+ private val kosmos = testKosmos()
+ private val msdlPlayer: FakeMSDLPlayer = kosmos.msdlPlayer
lateinit var underTest: EmergencyButtonController
@@ -84,6 +93,7 @@ class EmergencyButtonControllerTest : SysuiTestCase() {
mainExecutor,
backgroundExecutor,
mSelectedUserInteractor,
+ msdlPlayer,
)
context.setMockPackageManager(packageManager)
Mockito.`when`(emergencyButton.context).thenReturn(context)
@@ -113,4 +123,13 @@ class EmergencyButtonControllerTest : SysuiTestCase() {
/* isSecure= */ eq(true)
)
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
+ fun takeEmergencyCallAction_withMSDLFeedback_playsEmergencyButtonTokenAndNullAttributes() {
+ underTest.takeEmergencyCallAction()
+
+ assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.KEYPRESS_RETURN)
+ assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
index a18d272b8fe3..aa8c6b7a8a5f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ambient/touch/TouchMonitorTest.java
@@ -57,6 +57,7 @@ import com.android.systemui.Flags;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.ambient.touch.dagger.InputSessionComponent;
import com.android.systemui.kosmos.KosmosJavaAdapter;
+import com.android.systemui.log.LogBufferHelperKt;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.display.DisplayHelper;
@@ -153,7 +154,8 @@ public class TouchMonitorTest extends SysuiTestCase {
when(mWindowManager.getMaximumWindowMetrics()).thenReturn(mWindowMetrics);
mMonitor = new TouchMonitor(mExecutor, mBackgroundExecutor, mLifecycleRegistry,
mInputFactory, mDisplayHelper, mKosmos.getConfigurationInteractor(),
- handlers, mIWindowManager, 0);
+ handlers, mIWindowManager, 0, "TouchMonitorTest",
+ LogBufferHelperKt.logcatLogBuffer("TouchMonitorTest"));
clearInvocations(mLifecycleRegistry);
mMonitor.init();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
index 88bfcf00423f..a1bea0620528 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
@@ -39,8 +39,6 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.testing.FakeMetricsLogger;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.classifier.FalsingDataProvider.GestureFinalizedListener;
-import com.android.systemui.flags.FakeFeatureFlags;
-import com.android.systemui.flags.Flags;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -84,7 +82,6 @@ public class BrightLineClassifierTest extends SysuiTestCase {
private AccessibilityManager mAccessibilityManager;
private final FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
- private final FakeFeatureFlags mFakeFeatureFlags = new FakeFeatureFlags();
private final FalsingClassifier.Result mFalsedResult =
FalsingClassifier.Result.falsed(1, getClass().getSimpleName(), "");
@@ -110,7 +107,7 @@ public class BrightLineClassifierTest extends SysuiTestCase {
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
mMetricsLogger, mClassifiers, mSingleTapClassfier, mLongTapClassifier,
mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
- mAccessibilityManager, false, mFakeFeatureFlags);
+ mAccessibilityManager, false);
ArgumentCaptor<GestureFinalizedListener> gestureCompleteListenerCaptor =
@@ -120,7 +117,6 @@ public class BrightLineClassifierTest extends SysuiTestCase {
gestureCompleteListenerCaptor.capture());
mGestureFinalizedListener = gestureCompleteListenerCaptor.getValue();
- mFakeFeatureFlags.set(Flags.FALSING_OFF_FOR_UNFOLDED, true);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
new file mode 100644
index 000000000000..945f95385db2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialNotificationCoordinatorTest.kt
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.inputdevice.tutorial.domain.interactor
+
+import android.app.Notification
+import android.app.NotificationManager
+import androidx.annotation.StringRes
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.inputdevice.tutorial.data.repository.TutorialSchedulerRepository
+import com.android.systemui.inputdevice.tutorial.ui.TutorialNotificationCoordinator
+import com.android.systemui.keyboard.data.repository.FakeKeyboardRepository
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.res.R
+import com.android.systemui.touchpad.data.repository.FakeTouchpadRepository
+import com.google.common.truth.Truth.assertThat
+import kotlin.time.Duration.Companion.hours
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.cancel
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.advanceTimeBy
+import kotlinx.coroutines.test.runTest
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.junit.MockitoJUnit
+import org.mockito.kotlin.any
+import org.mockito.kotlin.eq
+import org.mockito.kotlin.never
+import org.mockito.kotlin.verify
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class TutorialNotificationCoordinatorTest : SysuiTestCase() {
+
+ private lateinit var underTest: TutorialNotificationCoordinator
+ private val kosmos = Kosmos()
+ private val testScope = kosmos.testScope
+ private val keyboardRepository = FakeKeyboardRepository()
+ private val touchpadRepository = FakeTouchpadRepository()
+ private lateinit var dataStoreScope: CoroutineScope
+ private lateinit var repository: TutorialSchedulerRepository
+ @Mock private lateinit var notificationManager: NotificationManager
+ @Captor private lateinit var notificationCaptor: ArgumentCaptor<Notification>
+ @get:Rule val rule = MockitoJUnit.rule()
+
+ @Before
+ fun setup() {
+ dataStoreScope = CoroutineScope(Dispatchers.Unconfined)
+ repository =
+ TutorialSchedulerRepository(
+ context,
+ dataStoreScope,
+ dataStoreName = "TutorialNotificationCoordinatorTest"
+ )
+ val interactor =
+ TutorialSchedulerInteractor(keyboardRepository, touchpadRepository, repository)
+ underTest =
+ TutorialNotificationCoordinator(
+ testScope.backgroundScope,
+ context,
+ interactor,
+ notificationManager
+ )
+ notificationCaptor = ArgumentCaptor.forClass(Notification::class.java)
+ underTest.start()
+ }
+
+ @After
+ fun clear() {
+ runBlocking { repository.clearDataStore() }
+ dataStoreScope.cancel()
+ }
+
+ @Test
+ fun showKeyboardNotification() =
+ testScope.runTest {
+ keyboardRepository.setIsAnyKeyboardConnected(true)
+ advanceTimeBy(LAUNCH_DELAY)
+ verifyNotification(
+ R.string.launch_keyboard_tutorial_notification_title,
+ R.string.launch_keyboard_tutorial_notification_content
+ )
+ }
+
+ @Test
+ fun showTouchpadNotification() =
+ testScope.runTest {
+ touchpadRepository.setIsAnyTouchpadConnected(true)
+ advanceTimeBy(LAUNCH_DELAY)
+ verifyNotification(
+ R.string.launch_touchpad_tutorial_notification_title,
+ R.string.launch_touchpad_tutorial_notification_content
+ )
+ }
+
+ @Test
+ fun showKeyboardTouchpadNotification() =
+ testScope.runTest {
+ keyboardRepository.setIsAnyKeyboardConnected(true)
+ touchpadRepository.setIsAnyTouchpadConnected(true)
+ advanceTimeBy(LAUNCH_DELAY)
+ verifyNotification(
+ R.string.launch_keyboard_touchpad_tutorial_notification_title,
+ R.string.launch_keyboard_touchpad_tutorial_notification_content
+ )
+ }
+
+ @Test
+ fun doNotShowNotification() =
+ testScope.runTest {
+ advanceTimeBy(LAUNCH_DELAY)
+ verify(notificationManager, never()).notify(eq(TAG), eq(NOTIFICATION_ID), any())
+ }
+
+ private fun verifyNotification(@StringRes titleResId: Int, @StringRes contentResId: Int) {
+ verify(notificationManager)
+ .notify(eq(TAG), eq(NOTIFICATION_ID), notificationCaptor.capture())
+ val notification = notificationCaptor.value
+ val actualTitle = notification.getString(Notification.EXTRA_TITLE)
+ val actualContent = notification.getString(Notification.EXTRA_TEXT)
+ assertThat(actualTitle).isEqualTo(context.getString(titleResId))
+ assertThat(actualContent).isEqualTo(context.getString(contentResId))
+ }
+
+ private fun Notification.getString(key: String): String =
+ this.extras?.getCharSequence(key).toString()
+
+ companion object {
+ private const val TAG = "TutorialSchedulerInteractor"
+ private const val NOTIFICATION_ID = 5566
+ private val LAUNCH_DELAY = 72.hours
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
index 432f7af7c29d..650f9dc7f104 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/inputdevice/tutorial/domain/interactor/TutorialSchedulerInteractorTest.kt
@@ -32,6 +32,8 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.cancel
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runTest
@@ -63,13 +65,7 @@ class TutorialSchedulerInteractorTest : SysuiTestCase() {
dataStoreName = "TutorialSchedulerInteractorTest"
)
underTest =
- TutorialSchedulerInteractor(
- testScope.backgroundScope,
- keyboardRepository,
- touchpadRepository,
- schedulerRepository
- )
- underTest.start()
+ TutorialSchedulerInteractor(keyboardRepository, touchpadRepository, schedulerRepository)
}
@After
@@ -81,80 +77,90 @@ class TutorialSchedulerInteractorTest : SysuiTestCase() {
@Test
fun connectKeyboard_delayElapse_launchForKeyboard() =
testScope.runTest {
+ launchAndAssert(TutorialType.KEYBOARD)
+
keyboardRepository.setIsAnyKeyboardConnected(true)
advanceTimeBy(LAUNCH_DELAY)
- assertLaunch(TutorialType.KEYBOARD)
}
@Test
fun connectBothDevices_delayElapse_launchForBoth() =
testScope.runTest {
+ launchAndAssert(TutorialType.BOTH)
+
keyboardRepository.setIsAnyKeyboardConnected(true)
touchpadRepository.setIsAnyTouchpadConnected(true)
advanceTimeBy(LAUNCH_DELAY)
- assertLaunch(TutorialType.BOTH)
}
@Test
fun connectBothDevice_delayNotElapse_launchNothing() =
testScope.runTest {
+ launchAndAssert(TutorialType.NONE)
+
keyboardRepository.setIsAnyKeyboardConnected(true)
touchpadRepository.setIsAnyTouchpadConnected(true)
advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
- assertLaunch(TutorialType.NONE)
}
@Test
fun nothingConnect_delayElapse_launchNothing() =
testScope.runTest {
+ launchAndAssert(TutorialType.NONE)
+
keyboardRepository.setIsAnyKeyboardConnected(false)
touchpadRepository.setIsAnyTouchpadConnected(false)
advanceTimeBy(LAUNCH_DELAY)
- assertLaunch(TutorialType.NONE)
}
@Test
fun connectKeyboard_thenTouchpad_delayElapse_launchForBoth() =
testScope.runTest {
+ launchAndAssert(TutorialType.BOTH)
+
keyboardRepository.setIsAnyKeyboardConnected(true)
advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
touchpadRepository.setIsAnyTouchpadConnected(true)
advanceTimeBy(REMAINING_TIME)
- assertLaunch(TutorialType.BOTH)
}
@Test
fun connectKeyboard_thenTouchpad_removeKeyboard_delayElapse_launchNothing() =
testScope.runTest {
+ launchAndAssert(TutorialType.NONE)
+
keyboardRepository.setIsAnyKeyboardConnected(true)
advanceTimeBy(A_SHORT_PERIOD_OF_TIME)
touchpadRepository.setIsAnyTouchpadConnected(true)
keyboardRepository.setIsAnyKeyboardConnected(false)
advanceTimeBy(REMAINING_TIME)
- assertLaunch(TutorialType.NONE)
}
- // TODO: likely to be changed after we update TutorialSchedulerInteractor.launchTutorial
- private suspend fun assertLaunch(tutorialType: TutorialType) {
- when (tutorialType) {
- TutorialType.KEYBOARD -> {
- assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
- assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
- }
- TutorialType.TOUCHPAD -> {
- assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
- assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
- }
- TutorialType.BOTH -> {
- assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
- assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
- }
- TutorialType.NONE -> {
- assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
- assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
+ private suspend fun launchAndAssert(expectedTutorial: TutorialType) =
+ testScope.backgroundScope.launch {
+ val actualTutorial = underTest.tutorials.first()
+ assertThat(actualTutorial).isEqualTo(expectedTutorial)
+
+ // TODO: need to update after we move launch into the tutorial
+ when (expectedTutorial) {
+ TutorialType.KEYBOARD -> {
+ assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
+ assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
+ }
+ TutorialType.TOUCHPAD -> {
+ assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
+ assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
+ }
+ TutorialType.BOTH -> {
+ assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isTrue()
+ assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isTrue()
+ }
+ TutorialType.NONE -> {
+ assertThat(schedulerRepository.isLaunched(DeviceType.KEYBOARD)).isFalse()
+ assertThat(schedulerRepository.isLaunched(DeviceType.TOUCHPAD)).isFalse()
+ }
}
}
- }
companion object {
private val LAUNCH_DELAY = 72.hours
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
index fd53b5baece5..ad7a5b62b912 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/LegacyMediaDataManagerImplTest.kt
@@ -56,7 +56,6 @@ import com.android.systemui.flags.Flags.MEDIA_REMOTE_RESUME
import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS
import com.android.systemui.flags.Flags.MEDIA_RETAIN_RECOMMENDATIONS
import com.android.systemui.flags.Flags.MEDIA_RETAIN_SESSIONS
-import com.android.systemui.flags.Flags.MEDIA_SESSION_ACTIONS
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
@@ -317,7 +316,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
whenever(mediaSmartspaceTarget.iconGrid).thenReturn(validRecommendationList)
whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(SMARTSPACE_CREATION_TIME)
whenever(mediaSmartspaceTarget.expiryTimeMillis).thenReturn(SMARTSPACE_EXPIRY_TIME)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, false)
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, false)
fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, false)
fakeFeatureFlags.set(MEDIA_REMOTE_RESUME, false)
@@ -1671,7 +1669,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testPlaybackActions_noState_usesNotification() {
val desc = "Notification Action"
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
whenever(controller.playbackState).thenReturn(null)
val notifWithAction =
@@ -1705,7 +1702,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testPlaybackActions_hasPrevNext() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions =
PlaybackState.ACTION_PLAY or
PlaybackState.ACTION_SKIP_TO_PREVIOUS or
@@ -1749,7 +1745,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testPlaybackActions_noPrevNext_usesCustom() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4", "custom 5")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
customDesc.forEach {
@@ -1781,7 +1776,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testPlaybackActions_connecting() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder =
PlaybackState.Builder()
@@ -1802,7 +1796,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testPlaybackActions_reservedSpace() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
customDesc.forEach {
@@ -1840,7 +1833,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testPlaybackActions_playPause_hasButton() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY_PAUSE
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
whenever(controller.playbackState).thenReturn(stateBuilder.build())
@@ -1939,7 +1931,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testPlaybackState_PauseWhenFlagTrue_keyExists_callsListener() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val state = PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 1f).build()
whenever(controller.playbackState).thenReturn(state)
@@ -2161,7 +2152,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testRetain_sessionPlayer_notifRemoved_doesNotChange() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2181,7 +2171,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testRetain_sessionPlayer_sessionDestroyed_setToResume() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2215,7 +2204,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testRetain_sessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions is added, and then the session is destroyed
@@ -2235,7 +2223,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testRetain_sessionPlayer_canResume_destroyedWhileActive_setToResume() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions and that does allow resumption is added,
@@ -2268,7 +2255,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testSessionPlayer_sessionDestroyed_noResume_fullyRemoved() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2295,7 +2281,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testSessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions is added, and then the session is destroyed
@@ -2314,7 +2299,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testSessionPlayer_canResume_destroyedWhileActive_setToResume() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions and that does allow resumption is added,
@@ -2348,7 +2332,6 @@ class LegacyMediaDataManagerImplTest(flags: FlagsParameterization) : SysuiTestCa
@Test
fun testSessionDestroyed_noNotificationKey_stillRemoved() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
// When a notiifcation is added and then removed before it is fully processed
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
index f4c2b47d6653..c0f503d7f1cb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/domain/pipeline/MediaDataProcessorTest.kt
@@ -61,7 +61,6 @@ import com.android.systemui.flags.Flags.MEDIA_REMOTE_RESUME
import com.android.systemui.flags.Flags.MEDIA_RESUME_PROGRESS
import com.android.systemui.flags.Flags.MEDIA_RETAIN_RECOMMENDATIONS
import com.android.systemui.flags.Flags.MEDIA_RETAIN_SESSIONS
-import com.android.systemui.flags.Flags.MEDIA_SESSION_ACTIONS
import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
@@ -338,7 +337,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
whenever(mediaSmartspaceTarget.iconGrid).thenReturn(validRecommendationList)
whenever(mediaSmartspaceTarget.creationTimeMillis).thenReturn(SMARTSPACE_CREATION_TIME)
whenever(mediaSmartspaceTarget.expiryTimeMillis).thenReturn(SMARTSPACE_EXPIRY_TIME)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, false)
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, false)
fakeFeatureFlags.set(MEDIA_RESUME_PROGRESS, false)
fakeFeatureFlags.set(MEDIA_REMOTE_RESUME, false)
@@ -1680,7 +1678,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testPlaybackActions_noState_usesNotification() {
val desc = "Notification Action"
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
whenever(controller.playbackState).thenReturn(null)
val notifWithAction =
@@ -1714,7 +1711,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testPlaybackActions_hasPrevNext() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions =
PlaybackState.ACTION_PLAY or
PlaybackState.ACTION_SKIP_TO_PREVIOUS or
@@ -1758,7 +1754,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testPlaybackActions_noPrevNext_usesCustom() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4", "custom 5")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
customDesc.forEach {
@@ -1790,7 +1785,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testPlaybackActions_connecting() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder =
PlaybackState.Builder()
@@ -1811,7 +1805,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
@EnableFlags(Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
fun postWithPlaybackActions_drawablesReused() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
val stateActions =
@@ -1845,7 +1838,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
@DisableFlags(Flags.FLAG_MEDIA_CONTROLS_DRAWABLES_REUSE)
fun postWithPlaybackActions_drawablesNotReused() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
whenever(notificationLockscreenUserManager.isCurrentProfile(USER_ID)).thenReturn(true)
whenever(notificationLockscreenUserManager.isProfileAvailable(USER_ID)).thenReturn(true)
val stateActions =
@@ -1879,7 +1871,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testPlaybackActions_reservedSpace() {
val customDesc = arrayOf("custom 1", "custom 2", "custom 3", "custom 4")
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
customDesc.forEach {
@@ -1917,7 +1908,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testPlaybackActions_playPause_hasButton() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val stateActions = PlaybackState.ACTION_PLAY_PAUSE
val stateBuilder = PlaybackState.Builder().setActions(stateActions)
whenever(controller.playbackState).thenReturn(stateBuilder.build())
@@ -2016,7 +2006,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testPlaybackState_PauseWhenFlagTrue_keyExists_callsListener() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
val state = PlaybackState.Builder().setState(PlaybackState.STATE_PAUSED, 0L, 1f).build()
whenever(controller.playbackState).thenReturn(state)
@@ -2237,7 +2226,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testRetain_sessionPlayer_notifRemoved_doesNotChange() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2257,7 +2245,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testRetain_sessionPlayer_sessionDestroyed_setToResume() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2291,7 +2278,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testRetain_sessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions is added, and then the session is destroyed
@@ -2311,7 +2297,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testRetain_sessionPlayer_canResume_destroyedWhileActive_setToResume() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions and that does allow resumption is added,
@@ -2344,7 +2329,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testSessionPlayer_sessionDestroyed_noResume_fullyRemoved() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control with PlaybackState actions is added, times out,
@@ -2371,7 +2355,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testSessionPlayer_destroyedWhileActive_noResume_fullyRemoved() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions is added, and then the session is destroyed
@@ -2390,7 +2373,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testSessionPlayer_canResume_destroyedWhileActive_setToResume() {
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
addPlaybackStateAction()
// When a media control using session actions and that does allow resumption is added,
@@ -2424,7 +2406,6 @@ class MediaDataProcessorTest(flags: FlagsParameterization) : SysuiTestCase() {
@Test
fun testSessionDestroyed_noNotificationKey_stillRemoved() {
fakeFeatureFlags.set(MEDIA_RETAIN_SESSIONS, true)
- fakeFeatureFlags.set(MEDIA_SESSION_ACTIONS, true)
// When a notiifcation is added and then removed before it is fully processed
mediaDataProcessor.onNotificationAdded(KEY, mediaNotification)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingStateTest.kt
new file mode 100644
index 000000000000..4ab3c7b203c4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/recordissue/IssueRecordingStateTest.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recordissue
+
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.kosmos.Kosmos
+import com.android.systemui.settings.userFileManager
+import com.android.systemui.settings.userTracker
+import com.google.common.truth.Truth
+import java.util.concurrent.CountDownLatch
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+class IssueRecordingStateTest : SysuiTestCase() {
+
+ private val kosmos = Kosmos()
+ private lateinit var underTest: IssueRecordingState
+
+ @Before
+ fun setup() {
+ underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+ }
+
+ @Test
+ fun takeBugreport_isSaved_betweenDifferentSessions() {
+ val expected = true
+
+ underTest.takeBugreport = expected
+ underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+ Truth.assertThat(underTest.takeBugreport).isEqualTo(expected)
+ }
+
+ @Test
+ fun recordScreen_isSaved_betweenDifferentSessions() {
+ val expected = true
+
+ underTest.recordScreen = expected
+ underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+ Truth.assertThat(underTest.recordScreen).isEqualTo(expected)
+ }
+
+ @Test
+ fun hasUserApprovedScreenRecording_isTrue_afterBeingMarkedAsCompleted() {
+ underTest.markUserApprovalForScreenRecording()
+ underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+ Truth.assertThat(underTest.hasUserApprovedScreenRecording).isEqualTo(true)
+ }
+
+ @Test
+ fun tagTitles_areSavedConsistently() {
+ val expected = setOf("a", "b", "c")
+
+ underTest.tagTitles = expected
+ underTest = IssueRecordingState(kosmos.userTracker, kosmos.userFileManager)
+
+ Truth.assertThat(underTest.tagTitles).isEqualTo(expected)
+ }
+
+ @Test
+ fun isRecording_callsListeners_onTheValueChanging() {
+ val count = CountDownLatch(1)
+ val listener = Runnable { count.countDown() }
+
+ underTest.addListener(listener)
+ underTest.isRecording = true
+
+ Truth.assertThat(count.count).isEqualTo(0)
+ }
+
+ @Test
+ fun isRecording_callsOnlyListeners_whoHaveNotBeenRemoved() {
+ val count1 = CountDownLatch(1)
+ val count2 = CountDownLatch(1)
+ val listener1 = Runnable { count1.countDown() }
+ val listener2 = Runnable { count2.countDown() }
+
+ underTest.addListener(listener1)
+ underTest.removeListener(listener1)
+ underTest.addListener(listener2)
+ underTest.isRecording = true
+
+ Truth.assertThat(count1.count).isEqualTo(1)
+ Truth.assertThat(count2.count).isEqualTo(0)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
index 3ba1447eb406..c0444fecb2bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/GlanceableHubContainerControllerTest.kt
@@ -117,7 +117,8 @@ class GlanceableHubContainerControllerTest : SysuiTestCase() {
object : AmbientTouchComponent.Factory {
override fun create(
lifecycleOwner: LifecycleOwner,
- touchHandlers: Set<TouchHandler>
+ touchHandlers: Set<TouchHandler>,
+ loggingName: String
): AmbientTouchComponent =
object : AmbientTouchComponent {
override fun getTouchMonitor(): TouchMonitor = touchMonitor
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
index a0d231b8bb6f..60a185537b0d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/StatusBarIconViewTest.java
@@ -51,6 +51,7 @@ import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.service.notification.StatusBarNotification;
import android.view.ViewGroup;
+import android.widget.ImageView;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -431,6 +432,32 @@ public class StatusBarIconViewTest extends SysuiTestCase {
mIconView.getIconScale(), 0.01f);
}
+ @Test
+ @EnableFlags({Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_ICONS})
+ public void set_iconThatWantsFixedSpace_setsScaleType() {
+ mIconView.setScaleType(ImageView.ScaleType.FIT_START);
+ StatusBarIcon icon = new StatusBarIcon(UserHandle.ALL, "mockPackage",
+ Icon.createWithResource(mContext, R.drawable.ic_android), 0, 0, "",
+ StatusBarIcon.Type.SystemIcon, StatusBarIcon.Shape.FIXED_SPACE);
+
+ mIconView.set(icon);
+
+ assertThat(mIconView.getScaleType()).isEqualTo(ImageView.ScaleType.FIT_CENTER);
+ }
+
+ @Test
+ @EnableFlags({Flags.FLAG_MODES_UI, Flags.FLAG_MODES_UI_ICONS})
+ public void set_iconWithOtherShape_keepsScaleType() {
+ mIconView.setScaleType(ImageView.ScaleType.FIT_START);
+ StatusBarIcon icon = new StatusBarIcon(UserHandle.ALL, "mockPackage",
+ Icon.createWithResource(mContext, R.drawable.ic_android), 0, 0, "",
+ StatusBarIcon.Type.SystemIcon, StatusBarIcon.Shape.WRAP_CONTENT);
+
+ mIconView.set(icon);
+
+ assertThat(mIconView.getScaleType()).isEqualTo(ImageView.ScaleType.FIT_START);
+ }
+
private static StatusBarNotification getMockSbn() {
StatusBarNotification sbn = mock(StatusBarNotification.class);
when(sbn.getNotification()).thenReturn(mock(Notification.class));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
index bd5df07b7ece..f528ebbd9e63 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModelTest.kt
@@ -107,69 +107,69 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
}
@Test
- fun chip_allHidden_hidden() =
+ fun primaryChip_allHidden_hidden() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.DoingNothing
mediaProjectionState.value = MediaProjectionState.NotProjecting
callRepo.setOngoingCallState(OngoingCallModel.NoCall)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertThat(latest).isInstanceOf(OngoingActivityChipModel.Hidden::class.java)
}
@Test
- fun chip_screenRecordShow_restHidden_screenRecordShown() =
+ fun primaryChip_screenRecordShow_restHidden_screenRecordShown() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value = MediaProjectionState.NotProjecting
callRepo.setOngoingCallState(OngoingCallModel.NoCall)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsScreenRecordChip(latest)
}
@Test
- fun chip_screenRecordShowAndCallShow_screenRecordShown() =
+ fun primaryChip_screenRecordShowAndCallShow_screenRecordShown() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.Recording
callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsScreenRecordChip(latest)
}
@Test
- fun chip_screenRecordShowAndShareToAppShow_screenRecordShown() =
+ fun primaryChip_screenRecordShowAndShareToAppShow_screenRecordShown() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
callRepo.setOngoingCallState(OngoingCallModel.NoCall)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsScreenRecordChip(latest)
}
@Test
- fun chip_shareToAppShowAndCallShow_shareToAppShown() =
+ fun primaryChip_shareToAppShowAndCallShow_shareToAppShown() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.DoingNothing
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsShareToAppChip(latest)
}
@Test
- fun chip_screenRecordAndShareToAppAndCastToOtherHideAndCallShown_callShown() =
+ fun primaryChip_screenRecordAndShareToAppAndCastToOtherHideAndCallShown_callShown() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.DoingNothing
// MediaProjection covers both share-to-app and cast-to-other-device
@@ -177,14 +177,14 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsCallChip(latest)
}
@Test
@EnableFlags(FLAG_STATUS_BAR_RON_CHIPS)
- fun chip_higherPriorityChipAdded_lowerPriorityChipReplaced() =
+ fun primaryChip_higherPriorityChipAdded_lowerPriorityChipReplaced() =
testScope.runTest {
// Start with just the lowest priority chip shown
addDemoRonChip(commandRegistry, pw)
@@ -193,7 +193,7 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
mediaProjectionState.value = MediaProjectionState.NotProjecting
screenRecordState.value = ScreenRecordModel.DoingNothing
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsDemoRonChip(latest)
@@ -223,7 +223,7 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
@Test
@EnableFlags(FLAG_STATUS_BAR_RON_CHIPS)
- fun chip_highestPriorityChipRemoved_showsNextPriorityChip() =
+ fun primaryChip_highestPriorityChipRemoved_showsNextPriorityChip() =
testScope.runTest {
// WHEN all chips are active
screenRecordState.value = ScreenRecordModel.Recording
@@ -232,7 +232,7 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
callRepo.setOngoingCallState(inCallModel(startTimeMs = 34))
addDemoRonChip(commandRegistry, pw)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
// THEN the highest priority screen record is used
assertIsScreenRecordChip(latest)
@@ -258,11 +258,11 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
/** Regression test for b/347726238. */
@Test
- fun chip_timerDoesNotResetAfterSubscribersRestart() =
+ fun primaryChip_timerDoesNotResetAfterSubscribersRestart() =
testScope.runTest {
var latest: OngoingActivityChipModel? = null
- val job1 = underTest.chip.onEach { latest = it }.launchIn(this)
+ val job1 = underTest.primaryChip.onEach { latest = it }.launchIn(this)
// Start a chip with a timer
systemClock.setElapsedRealtime(1234)
@@ -279,7 +279,7 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
systemClock.setElapsedRealtime(5678)
// WHEN we re-subscribe to the chip flow
- val job2 = underTest.chip.onEach { latest = it }.launchIn(this)
+ val job2 = underTest.primaryChip.onEach { latest = it }.launchIn(this)
runCurrent()
@@ -290,13 +290,13 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
}
@Test
- fun chip_screenRecordStoppedViaDialog_chipHiddenWithoutAnimation() =
+ fun primaryChip_screenRecordStoppedViaDialog_chipHiddenWithoutAnimation() =
testScope.runTest {
screenRecordState.value = ScreenRecordModel.Recording
mediaProjectionState.value = MediaProjectionState.NotProjecting
callRepo.setOngoingCallState(OngoingCallModel.NoCall)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsScreenRecordChip(latest)
@@ -310,14 +310,14 @@ class OngoingActivityChipsViewModelTest : SysuiTestCase() {
}
@Test
- fun chip_projectionStoppedViaDialog_chipHiddenWithoutAnimation() =
+ fun primaryChip_projectionStoppedViaDialog_chipHiddenWithoutAnimation() =
testScope.runTest {
mediaProjectionState.value =
MediaProjectionState.Projecting.EntireScreen(NORMAL_PACKAGE)
screenRecordState.value = ScreenRecordModel.DoingNothing
callRepo.setOngoingCallState(OngoingCallModel.NoCall)
- val latest by collectLastValue(underTest.chip)
+ val latest by collectLastValue(underTest.primaryChip)
assertIsShareToAppChip(latest)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index a18de68dfcfc..a06f4d2d2d80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -95,6 +95,8 @@ import com.android.systemui.statusbar.notification.footer.ui.view.FooterView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.shared.NotificationThrottleHun;
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds;
+import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.ScreenOffAnimationController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
@@ -893,7 +895,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test
@DisableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
- @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+ @DisableSceneContainer
public void testInsideQSHeader_noOffset() {
ViewGroup qsHeader = mock(ViewGroup.class);
Rect boundsOnScreen = new Rect(0, 0, 1000, 1000);
@@ -911,7 +913,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test
@DisableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
- @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+ @DisableSceneContainer
public void testInsideQSHeader_Offset() {
ViewGroup qsHeader = mock(ViewGroup.class);
Rect boundsOnScreen = new Rect(100, 100, 1000, 1000);
@@ -932,7 +934,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test
@EnableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
- @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+ @DisableSceneContainer
public void testInsideQSHeader_noOffset_qsCompose() {
ViewGroup qsHeader = mock(ViewGroup.class);
Rect boundsOnScreen = new Rect(0, 0, 1000, 1000);
@@ -959,7 +961,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test
@EnableFlags({QSComposeFragment.FLAG_NAME, NewQsUI.FLAG_NAME})
- @DisableSceneContainer // TODO(b/312473478): address lack of QS Header
+ @DisableSceneContainer
public void testInsideQSHeader_Offset_qsCompose() {
ViewGroup qsHeader = mock(ViewGroup.class);
Rect boundsOnScreen = new Rect(100, 100, 1000, 1000);
@@ -988,6 +990,53 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
}
@Test
+ @EnableSceneContainer
+ public void testIsInsideScrollableRegion_noScrim() {
+ mStackScroller.setLeftTopRightBottom(0, 0, 2000, 2000);
+
+ MotionEvent event = transformEventForView(createMotionEvent(250f, 250f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event)).isTrue();
+ }
+
+ @Test
+ @EnableSceneContainer
+ public void testIsInsideScrollableRegion_noOffset() {
+ mStackScroller.setLeftTopRightBottom(0, 0, 1000, 2000);
+ mStackScroller.setScrimClippingShape(createScrimShape(100, 500, 900, 2000));
+
+ MotionEvent event1 = transformEventForView(createMotionEvent(500f, 400f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event1)).isFalse();
+
+ MotionEvent event2 = transformEventForView(createMotionEvent(50, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event2)).isFalse();
+
+ MotionEvent event3 = transformEventForView(createMotionEvent(950f, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event3)).isFalse();
+
+ MotionEvent event4 = transformEventForView(createMotionEvent(500f, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event4)).isTrue();
+ }
+
+ @Test
+ @EnableSceneContainer
+ public void testIsInsideScrollableRegion_offset() {
+ mStackScroller.setLeftTopRightBottom(1000, 0, 2000, 2000);
+ mStackScroller.setScrimClippingShape(createScrimShape(100, 500, 900, 2000));
+
+ MotionEvent event1 = transformEventForView(createMotionEvent(1500f, 400f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event1)).isFalse();
+
+ MotionEvent event2 = transformEventForView(createMotionEvent(1050, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event2)).isFalse();
+
+ MotionEvent event3 = transformEventForView(createMotionEvent(1950f, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event3)).isFalse();
+
+ MotionEvent event4 = transformEventForView(createMotionEvent(1500f, 1000f), mStackScroller);
+ assertThat(mStackScroller.isInScrollableRegion(event4)).isTrue();
+ }
+
+ @Test
@DisableSceneContainer // TODO(b/312473478): address disabled test
public void setFractionToShade_recomputesStackHeight() {
mStackScroller.setFractionToShade(1f);
@@ -1438,7 +1487,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
private static MotionEvent transformEventForView(MotionEvent event, View view) {
// From `ViewGroup#dispatchTransformedTouchEvent`
MotionEvent transformed = event.copy();
- transformed.offsetLocation(-view.getTop(), -view.getLeft());
+ transformed.offsetLocation(/* deltaX = */-view.getLeft(), /* deltaY = */ -view.getTop());
return transformed;
}
@@ -1474,4 +1523,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
}
private abstract static class BooleanConsumer implements Consumer<Boolean> { }
+
+ private ShadeScrimShape createScrimShape(int left, int top, int right, int bottom) {
+ ShadeScrimBounds bounds = new ShadeScrimBounds(left, top, right, bottom);
+ return new ShadeScrimShape(bounds, 0, 0);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
index bea027f0e98b..6e337efd68af 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java
@@ -432,8 +432,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -445,8 +444,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
assertEquals(View.INVISIBLE, getNotificationAreaView().getVisibility());
}
@@ -460,8 +458,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
fragment.disable(DEFAULT_DISPLAY,
StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -474,8 +471,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -487,22 +483,19 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
// Ongoing call ended
when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
// Ongoing call started
when(mOngoingCallController.hasOngoingCall()).thenReturn(true);
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -536,8 +529,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
/* hasOngoingActivity= */ false, /* shouldAnimate= */ false);
// THEN the old callback value is used, so the view is shown
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
// WHEN there's *no* ongoing call via old callback
when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
@@ -548,8 +540,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
/* hasOngoingActivity= */ true, /* shouldAnimate= */ false);
// THEN the old callback value is used, so the view is hidden
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -564,8 +555,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
mCollapsedStatusBarViewBinder.getListener().onOngoingActivityStatusChanged(
/* hasOngoingActivity= */ false, /* shouldAnimate= */ false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -576,8 +566,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
mCollapsedStatusBarViewBinder.getListener().onOngoingActivityStatusChanged(
/* hasOngoingActivity= */ true, /* shouldAnimate= */ false);
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
assertEquals(View.INVISIBLE, getNotificationAreaView().getVisibility());
}
@@ -592,8 +581,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
fragment.disable(DEFAULT_DISPLAY,
StatusBarManager.DISABLE_NOTIFICATION_ICONS, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -607,8 +595,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
fragment.disable(DEFAULT_DISPLAY, 0, 0, false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -620,15 +607,13 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
mCollapsedStatusBarViewBinder.getListener().onOngoingActivityStatusChanged(
/* hasOngoingActivity= */ true, /* shouldAnimate= */ false);
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
// Ongoing activity ended
mCollapsedStatusBarViewBinder.getListener().onOngoingActivityStatusChanged(
/* hasOngoingActivity= */ false, /* shouldAnimate= */ false);
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -661,8 +646,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
/* hasOngoingActivity= */ false, /* shouldAnimate= */ false);
// THEN the new callback value is used, so the view is hidden
- assertEquals(View.GONE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.GONE, getPrimaryOngoingActivityChipView().getVisibility());
// WHEN there's *no* ongoing call via old callback
when(mOngoingCallController.hasOngoingCall()).thenReturn(false);
@@ -673,8 +657,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
/* hasOngoingActivity= */ true, /* shouldAnimate= */ false);
// THEN the new callback value is used, so the view is shown
- assertEquals(View.VISIBLE,
- mFragment.getView().findViewById(R.id.ongoing_activity_chip).getVisibility());
+ assertEquals(View.VISIBLE, getPrimaryOngoingActivityChipView().getVisibility());
}
@Test
@@ -1023,4 +1006,8 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest {
private View getNotificationAreaView() {
return mFragment.getView().findViewById(R.id.notificationIcons);
}
+
+ private View getPrimaryOngoingActivityChipView() {
+ return mFragment.getView().findViewById(R.id.ongoing_activity_chip_primary);
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
index 6de2caa59dd3..4b6e31303f79 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/data/repository/prod/MobileConnectionsRepositoryTest.kt
@@ -106,11 +106,7 @@ import org.mockito.kotlin.whenever
class MobileConnectionsRepositoryTest : SysuiTestCase() {
private val flags =
- FakeFeatureFlagsClassic().also {
- it.set(Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO, true)
- it.set(Flags.INSTANT_TETHER, true)
- it.set(Flags.WIFI_SECONDARY_NETWORKS, true)
- }
+ FakeFeatureFlagsClassic().also { it.set(Flags.ROAMING_INDICATOR_VIA_DISPLAY_INFO, true) }
private lateinit var connectionFactory: MobileConnectionRepositoryImpl.Factory
private lateinit var carrierMergedFactory: CarrierMergedConnectionRepository.Factory
@@ -189,7 +185,6 @@ class MobileConnectionsRepositoryTest : SysuiTestCase() {
wifiRepository =
WifiRepositoryImpl(
- flags,
testScope.backgroundScope,
mainExecutor,
testDispatcher,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
index 60750cf96e67..7ae6ea51b912 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/CollapsedStatusBarViewModelImplTest.kt
@@ -415,9 +415,9 @@ class CollapsedStatusBarViewModelImplTest : SysuiTestCase() {
}
@Test
- fun ongoingActivityChip_matchesViewModel() =
+ fun primaryOngoingActivityChip_matchesViewModel() =
testScope.runTest {
- val latest by collectLastValue(underTest.ongoingActivityChip)
+ val latest by collectLastValue(underTest.primaryOngoingActivityChip)
kosmos.screenRecordRepository.screenRecordState.value = ScreenRecordModel.Recording
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
index cefdf7e43fae..e71f5217095c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/FakeCollapsedStatusBarViewModel.kt
@@ -28,7 +28,7 @@ class FakeCollapsedStatusBarViewModel : CollapsedStatusBarViewModel {
override val transitionFromLockscreenToDreamStartedEvent = MutableSharedFlow<Unit>()
- override val ongoingActivityChip: MutableStateFlow<OngoingActivityChipModel> =
+ override val primaryOngoingActivityChip: MutableStateFlow<OngoingActivityChipModel> =
MutableStateFlow(OngoingActivityChipModel.Hidden())
override val isHomeStatusBarAllowedByScene = MutableStateFlow(false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
index f8d50f5e1ac2..b9c57d8be650 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/prod/WifiRepositoryImplTest.kt
@@ -25,8 +25,6 @@ import android.testing.TestableLooper
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
-import com.android.systemui.flags.Flags
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.connectivity.WifiPickerTrackerFactory
@@ -76,7 +74,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
// inside each test case without needing to manually recreate the repository.
private val underTest: WifiRepositoryImpl by lazy {
WifiRepositoryImpl(
- featureFlags,
testScope.backgroundScope,
executor,
dispatcher,
@@ -89,7 +86,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
private val executor = FakeExecutor(FakeSystemClock())
private val logger = LogBuffer("name", maxSize = 100, logcatEchoTracker = mock())
- private val featureFlags = FakeFeatureFlags()
private val tableLogger = mock<TableLogBuffer>()
private val wifiManager =
mock<WifiManager>().apply { whenever(this.maxSignalLevel).thenReturn(10) }
@@ -103,8 +99,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Before
fun setUp() {
- featureFlags.set(Flags.INSTANT_TETHER, false)
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, false)
whenever(wifiPickerTrackerFactory.create(any(), capture(callbackCaptor), any()))
.thenReturn(wifiPickerTracker)
}
@@ -394,7 +388,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun wifiNetwork_notHotspot_none() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry =
@@ -409,7 +402,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun wifiNetwork_hotspot_unknown() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_UNKNOWN)
@@ -423,7 +415,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun wifiNetwork_hotspot_phone() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_PHONE)
@@ -437,7 +428,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun wifiNetwork_hotspot_tablet() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_TABLET)
@@ -451,7 +441,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun wifiNetwork_hotspot_laptop() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_LAPTOP)
@@ -465,7 +454,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun wifiNetwork_hotspot_watch() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH)
@@ -479,7 +467,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun wifiNetwork_hotspot_auto() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_AUTO)
@@ -493,7 +480,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun wifiNetwork_hotspot_invalid() =
testScope.runTest {
- featureFlags.set(Flags.INSTANT_TETHER, true)
val latest by collectLastValue(underTest.wifiNetwork)
val wifiEntry = createHotspotWithType(1234)
@@ -505,23 +491,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun wifiNetwork_hotspot_flagOff_valueNotUsed() =
- testScope.runTest {
- // WHEN the flag is off
- featureFlags.set(Flags.INSTANT_TETHER, false)
-
- val latest by collectLastValue(underTest.wifiNetwork)
-
- val wifiEntry = createHotspotWithType(NetworkProviderInfo.DEVICE_TYPE_WATCH)
- whenever(wifiPickerTracker.connectedWifiEntry).thenReturn(wifiEntry)
- getCallback().onWifiEntriesChanged()
-
- // THEN NONE is always used, even if the wifi entry does have a hotspot device type
- assertThat((latest as WifiNetworkModel.Active).hotspotDeviceType)
- .isEqualTo(WifiNetworkModel.HotspotDeviceType.NONE)
- }
-
- @Test
fun wifiNetwork_isCarrierMerged_flowHasCarrierMerged() =
testScope.runTest {
val latest by collectLastValue(underTest.wifiNetwork)
@@ -826,7 +795,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun secondaryNetworks_activeEntriesEmpty_isEmpty() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf())
@@ -839,7 +807,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun secondaryNetworks_oneActiveEntry_hasOne() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val wifiEntry = mock<WifiEntry>()
@@ -853,7 +820,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun secondaryNetworks_multipleActiveEntries_hasMultiple() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val wifiEntry1 = mock<WifiEntry>()
@@ -868,7 +834,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun secondaryNetworks_mapsToInactive() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val inactiveEntry =
@@ -884,7 +849,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun secondaryNetworks_mapsToActive() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val activeEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
@@ -900,7 +864,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun secondaryNetworks_mapsToCarrierMerged() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val carrierMergedEntry =
@@ -917,7 +880,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun secondaryNetworks_mapsMultipleInOrder() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val activeEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
@@ -937,7 +899,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun secondaryNetworks_filtersOutConnectedEntry() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val connectedEntry = mock<WifiEntry>().apply { whenever(this.level).thenReturn(1) }
@@ -959,7 +920,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun secondaryNetworks_noConnectedEntry_hasAllActiveEntries() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val secondaryEntry1 = mock<WifiEntry>().apply { whenever(this.level).thenReturn(2) }
@@ -978,7 +938,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
@Test
fun secondaryNetworks_filtersOutPrimaryNetwork() =
testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, true)
val latest by collectLastValue(underTest.secondaryNetworks)
val primaryEntry =
@@ -1001,20 +960,6 @@ class WifiRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun secondaryNetworks_flagOff_noNetworks() =
- testScope.runTest {
- featureFlags.set(Flags.WIFI_SECONDARY_NETWORKS, false)
- val latest by collectLastValue(underTest.secondaryNetworks)
-
- val wifiEntry = mock<WifiEntry>()
- whenever(wifiPickerTracker.activeWifiEntries).thenReturn(listOf(wifiEntry))
-
- getCallback().onWifiEntriesChanged()
-
- assertThat(latest).isEmpty()
- }
-
- @Test
fun isWifiConnectedWithValidSsid_inactiveNetwork_false() =
testScope.runTest {
collectLastValue(underTest.wifiNetwork)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
index 171be97bf964..649e4e8a6f7e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelKosmos.kt
@@ -33,16 +33,16 @@ import com.android.systemui.user.ui.viewmodel.userSwitcherViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.StateFlow
-val Kosmos.bouncerSceneActionsViewModel by Fixture {
- BouncerSceneActionsViewModel(
+val Kosmos.bouncerUserActionsViewModel by Fixture {
+ BouncerUserActionsViewModel(
bouncerInteractor = bouncerInteractor,
)
}
-val Kosmos.bouncerSceneActionsViewModelFactory by Fixture {
- object : BouncerSceneActionsViewModel.Factory {
- override fun create(): BouncerSceneActionsViewModel {
- return bouncerSceneActionsViewModel
+val Kosmos.bouncerUserActionsViewModelFactory by Fixture {
+ object : BouncerUserActionsViewModel.Factory {
+ override fun create(): BouncerUserActionsViewModel {
+ return bouncerUserActionsViewModel
}
}
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelKosmos.kt
index 128a7fcbab25..06592b1ea3ed 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeUserActionsViewModelKosmos.kt
@@ -18,9 +18,9 @@ package com.android.systemui.qs.ui.viewmodel
import com.android.systemui.kosmos.Kosmos
-val Kosmos.quickSettingsShadeSceneActionsViewModel: QuickSettingsShadeSceneActionsViewModel by
+val Kosmos.quickSettingsShadeUserActionsViewModel: QuickSettingsShadeUserActionsViewModel by
Kosmos.Fixture {
- QuickSettingsShadeSceneActionsViewModel(
+ QuickSettingsShadeUserActionsViewModel(
quickSettingsContainerViewModel = quickSettingsContainerViewModel,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeUserActionsViewModelKosmos.kt
index f792ab95e8ac..6345c4076412 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeUserActionsViewModelKosmos.kt
@@ -18,7 +18,7 @@ package com.android.systemui.shade.ui.viewmodel
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
-import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneActionsViewModel
+import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeUserActionsViewModel
-val Kosmos.notificationsShadeSceneActionsViewModel:
- NotificationsShadeSceneActionsViewModel by Fixture { NotificationsShadeSceneActionsViewModel() }
+val Kosmos.notificationsShadeUserActionsViewModel:
+ NotificationsShadeUserActionsViewModel by Fixture { NotificationsShadeUserActionsViewModel() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelKosmos.kt
index 2387aa856fe6..48c5121c71c1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneActionsViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/ShadeUserActionsViewModelKosmos.kt
@@ -21,8 +21,8 @@ import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.qs.ui.adapter.qsSceneAdapter
import com.android.systemui.shade.domain.interactor.shadeInteractor
-val Kosmos.shadeSceneActionsViewModel: ShadeSceneActionsViewModel by Fixture {
- ShadeSceneActionsViewModel(
+val Kosmos.shadeUserActionsViewModel: ShadeUserActionsViewModel by Fixture {
+ ShadeUserActionsViewModel(
qsSceneAdapter = qsSceneAdapter,
shadeInteractor = shadeInteractor,
)
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
index 1fa6c3f2327b..888351f0a882 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/volume/data/repository/FakeAudioRepository.kt
@@ -33,6 +33,12 @@ import kotlinx.coroutines.flow.update
class FakeAudioRepository : AudioRepository {
+ private val unMutableStreams =
+ setOf(
+ AudioManager.STREAM_VOICE_CALL,
+ AudioManager.STREAM_ALARM,
+ )
+
private val mutableMode = MutableStateFlow(AudioManager.MODE_NORMAL)
override val mode: StateFlow<Int> = mutableMode.asStateFlow()
@@ -73,7 +79,7 @@ class FakeAudioRepository : AudioRepository {
volume = 0,
minVolume = 0,
maxVolume = 10,
- isAffectedByMute = false,
+ isAffectedByMute = audioStream.value !in unMutableStreams,
isAffectedByRingerMode = false,
isMuted = false,
)
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index d16a66522e51..1b2447e2c58a 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -26,6 +26,7 @@ import android.annotation.MainThread;
import android.annotation.NonNull;
import android.content.Context;
import android.graphics.Region;
+import android.hardware.input.InputManager;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemClock;
@@ -57,6 +58,7 @@ import com.android.server.policy.WindowManagerPolicy;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Objects;
import java.util.StringJoiner;
/**
@@ -748,6 +750,7 @@ class AccessibilityInputFilter extends InputFilter implements EventStreamTransfo
if ((mEnabledFeatures & FLAG_FEATURE_MOUSE_KEYS) != 0) {
mMouseKeysInterceptor = new MouseKeysInterceptor(mAms,
+ Objects.requireNonNull(mContext.getSystemService(InputManager.class)),
Looper.myLooper(),
Display.DEFAULT_DISPLAY);
addFirstEventHandler(Display.DEFAULT_DISPLAY, mMouseKeysInterceptor);
diff --git a/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java b/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java
index 2ce5c2bc3790..54368ca9c03e 100644
--- a/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java
+++ b/services/accessibility/java/com/android/server/accessibility/MouseKeysInterceptor.java
@@ -23,6 +23,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.companion.virtual.VirtualDeviceManager;
import android.companion.virtual.VirtualDeviceParams;
+import android.hardware.input.InputManager;
import android.hardware.input.VirtualMouse;
import android.hardware.input.VirtualMouseButtonEvent;
import android.hardware.input.VirtualMouseConfig;
@@ -34,8 +35,11 @@ import android.os.Message;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
+import android.view.InputDevice;
import android.view.KeyEvent;
+import androidx.annotation.VisibleForTesting;
+
import com.android.server.LocalServices;
import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
@@ -60,7 +64,7 @@ import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
* mouse keys of each physical keyboard will control a single (global) mouse pointer.
*/
public class MouseKeysInterceptor extends BaseEventStreamTransformation
- implements Handler.Callback {
+ implements Handler.Callback, InputManager.InputDeviceListener {
private static final String LOG_TAG = "MouseKeysInterceptor";
// To enable these logs, run: 'adb shell setprop log.tag.MouseKeysInterceptor DEBUG'
@@ -77,10 +81,19 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
private final AccessibilityManagerService mAms;
private final Handler mHandler;
+ private final InputManager mInputManager;
/** Thread to wait for virtual mouse creation to complete */
private final Thread mCreateVirtualMouseThread;
+ /**
+ * Map of device IDs to a map of key codes to their corresponding {@link MouseKeyEvent} values.
+ * To ensure thread safety for the map, all access and modification of the map
+ * should happen on the same thread, i.e., on the handler thread.
+ */
+ private final SparseArray<SparseArray<MouseKeyEvent>> mDeviceKeyCodeMap =
+ new SparseArray<>();
+
VirtualDeviceManager.VirtualDevice mVirtualDevice = null;
private VirtualMouse mVirtualMouse = null;
@@ -102,6 +115,21 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
/** Whether scroll toggle is on */
private boolean mScrollToggleOn = false;
+ /** The ID of the input device that is currently active */
+ private int mActiveInputDeviceId = 0;
+
+ /**
+ * Enum representing different types of mouse key events, each associated with a specific
+ * key code.
+ *
+ * <p> These events correspond to various mouse actions such as directional movements,
+ * clicks, and scrolls, mapped to specific keys on the keyboard.
+ * The key codes here are the QWERTY key codes, and should be accessed via
+ * {@link MouseKeyEvent#getKeyCode(InputDevice)}
+ * so that it is mapped to the equivalent key on the keyboard layout of the keyboard device
+ * that is actually in use.
+ * </p>
+ */
public enum MouseKeyEvent {
DIAGONAL_UP_LEFT_MOVE(KeyEvent.KEYCODE_7),
UP_MOVE_OR_SCROLL(KeyEvent.KEYCODE_8),
@@ -117,34 +145,64 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
RELEASE(KeyEvent.KEYCODE_COMMA),
SCROLL_TOGGLE(KeyEvent.KEYCODE_PERIOD);
- private final int mKeyCode;
+ private final int mLocationKeyCode;
MouseKeyEvent(int enumValue) {
- mKeyCode = enumValue;
+ mLocationKeyCode = enumValue;
}
- private static final SparseArray<MouseKeyEvent> VALUE_TO_ENUM_MAP = new SparseArray<>();
-
- static {
- for (MouseKeyEvent type : MouseKeyEvent.values()) {
- VALUE_TO_ENUM_MAP.put(type.mKeyCode, type);
- }
+ @VisibleForTesting
+ public final int getKeyCodeValue() {
+ return mLocationKeyCode;
}
- public final int getKeyCodeValue() {
- return mKeyCode;
+ /**
+ * Get the key code associated with the given MouseKeyEvent for the given keyboard
+ * input device, taking into account its layout.
+ * The default is to return the keycode for the default layout (QWERTY).
+ * We check if the input device has been generated using {@link InputDevice#getGeneration()}
+ * to test with the default {@link MouseKeyEvent} values in the unit tests.
+ */
+ public int getKeyCode(InputDevice inputDevice) {
+ if (inputDevice.getGeneration() == -1) {
+ return mLocationKeyCode;
+ }
+ return inputDevice.getKeyCodeForKeyLocation(mLocationKeyCode);
}
/**
- * Convert int value of the key code to corresponding MouseEvent enum. If no matching
- * value is found, this will return {@code null}.
+ * Convert int value of the key code to corresponding {@link MouseKeyEvent}
+ * enum for a particular device ID.
+ * If no matching value is found, this will return {@code null}.
*/
@Nullable
- public static MouseKeyEvent from(int value) {
- return VALUE_TO_ENUM_MAP.get(value);
+ public static MouseKeyEvent from(int keyCode, int deviceId,
+ SparseArray<SparseArray<MouseKeyEvent>> deviceKeyCodeMap) {
+ SparseArray<MouseKeyEvent> keyCodeToEnumMap = deviceKeyCodeMap.get(deviceId);
+ if (keyCodeToEnumMap != null) {
+ return keyCodeToEnumMap.get(keyCode);
+ }
+ return null;
}
}
/**
+ * Create a map of key codes to their corresponding {@link MouseKeyEvent} values
+ * for a specific input device.
+ * The key for {@code mDeviceKeyCodeMap} is the deviceId.
+ * The key for {@code keyCodeToEnumMap} is the keycode for each
+ * {@link MouseKeyEvent} according to the keyboard layout of the input device.
+ */
+ public void initializeDeviceToEnumMap(InputDevice inputDevice) {
+ int deviceId = inputDevice.getId();
+ SparseArray<MouseKeyEvent> keyCodeToEnumMap = new SparseArray<>();
+ for (MouseKeyEvent mouseKeyEventType : MouseKeyEvent.values()) {
+ int keyCode = mouseKeyEventType.getKeyCode(inputDevice);
+ keyCodeToEnumMap.put(keyCode, mouseKeyEventType);
+ }
+ mDeviceKeyCodeMap.put(deviceId, keyCodeToEnumMap);
+ }
+
+ /**
* Construct a new MouseKeysInterceptor.
*
* @param service The service to notify of key events
@@ -152,8 +210,10 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
* @param displayId Display ID to send mouse events to
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
- public MouseKeysInterceptor(AccessibilityManagerService service, Looper looper, int displayId) {
+ public MouseKeysInterceptor(AccessibilityManagerService service,
+ InputManager inputManager, Looper looper, int displayId) {
mAms = service;
+ mInputManager = inputManager;
mHandler = new Handler(looper, this);
// Create the virtual mouse on a separate thread since virtual device creation
// should happen on an auxiliary thread, and not from the handler's thread.
@@ -163,6 +223,9 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
mVirtualMouse = createVirtualMouse(displayId);
});
mCreateVirtualMouseThread.start();
+ // Register an input device listener to watch when input devices are
+ // added, removed or reconfigured.
+ mInputManager.registerInputDeviceListener(this, mHandler);
}
/**
@@ -215,7 +278,8 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
private void performMouseScrollAction(int keyCode) {
- MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(keyCode);
+ MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(
+ keyCode, mActiveInputDeviceId, mDeviceKeyCodeMap);
float y = switch (mouseKeyEvent) {
case UP_MOVE_OR_SCROLL -> 1.0f;
case DOWN_MOVE_OR_SCROLL -> -1.0f;
@@ -247,15 +311,18 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
private void performMouseButtonAction(int keyCode) {
- MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(keyCode);
+ MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(
+ keyCode, mActiveInputDeviceId, mDeviceKeyCodeMap);
int buttonCode = switch (mouseKeyEvent) {
case LEFT_CLICK -> VirtualMouseButtonEvent.BUTTON_PRIMARY;
case RIGHT_CLICK -> VirtualMouseButtonEvent.BUTTON_SECONDARY;
default -> VirtualMouseButtonEvent.BUTTON_UNKNOWN;
};
if (buttonCode != VirtualMouseButtonEvent.BUTTON_UNKNOWN) {
- sendVirtualMouseButtonEvent(buttonCode, VirtualMouseButtonEvent.ACTION_BUTTON_PRESS);
- sendVirtualMouseButtonEvent(buttonCode, VirtualMouseButtonEvent.ACTION_BUTTON_RELEASE);
+ sendVirtualMouseButtonEvent(buttonCode,
+ VirtualMouseButtonEvent.ACTION_BUTTON_PRESS);
+ sendVirtualMouseButtonEvent(buttonCode,
+ VirtualMouseButtonEvent.ACTION_BUTTON_RELEASE);
}
if (DEBUG) {
if (buttonCode == VirtualMouseButtonEvent.BUTTON_UNKNOWN) {
@@ -293,7 +360,9 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
private void performMousePointerAction(int keyCode) {
float x = 0f;
float y = 0f;
- MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(keyCode);
+ MouseKeyEvent mouseKeyEvent = MouseKeyEvent.from(
+ keyCode, mActiveInputDeviceId, mDeviceKeyCodeMap);
+
switch (mouseKeyEvent) {
case DIAGONAL_DOWN_LEFT_MOVE -> {
x = -MOUSE_POINTER_MOVEMENT_STEP / sqrt(2);
@@ -339,18 +408,19 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
}
}
- private boolean isMouseKey(int keyCode) {
- return MouseKeyEvent.VALUE_TO_ENUM_MAP.contains(keyCode);
+ private boolean isMouseKey(int keyCode, int deviceId) {
+ SparseArray<MouseKeyEvent> keyCodeToEnumMap = mDeviceKeyCodeMap.get(deviceId);
+ return keyCodeToEnumMap.contains(keyCode);
}
- private boolean isMouseButtonKey(int keyCode) {
- return keyCode == MouseKeyEvent.LEFT_CLICK.getKeyCodeValue()
- || keyCode == MouseKeyEvent.RIGHT_CLICK.getKeyCodeValue();
+ private boolean isMouseButtonKey(int keyCode, InputDevice inputDevice) {
+ return keyCode == MouseKeyEvent.LEFT_CLICK.getKeyCode(inputDevice)
+ || keyCode == MouseKeyEvent.RIGHT_CLICK.getKeyCode(inputDevice);
}
- private boolean isMouseScrollKey(int keyCode) {
- return keyCode == MouseKeyEvent.UP_MOVE_OR_SCROLL.getKeyCodeValue()
- || keyCode == MouseKeyEvent.DOWN_MOVE_OR_SCROLL.getKeyCodeValue();
+ private boolean isMouseScrollKey(int keyCode, InputDevice inputDevice) {
+ return keyCode == MouseKeyEvent.UP_MOVE_OR_SCROLL.getKeyCode(inputDevice)
+ || keyCode == MouseKeyEvent.DOWN_MOVE_OR_SCROLL.getKeyCode(inputDevice);
}
/**
@@ -373,7 +443,7 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
}
/**
- * Handles key events and forwards mouse key events to the virtual mouse.
+ * Handles key events and forwards mouse key events to the virtual mouse on the handler thread.
*
* @param event The key event to handle.
* @param policyFlags The policy flags associated with the key event.
@@ -385,31 +455,45 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
mAms.getTraceManager().logTrace(LOG_TAG + ".onKeyEvent",
FLAGS_INPUT_FILTER, "event=" + event + ";policyFlags=" + policyFlags);
}
+
+ mHandler.post(() -> {
+ onKeyEventInternal(event, policyFlags);
+ });
+ }
+
+ @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
+ private void onKeyEventInternal(KeyEvent event, int policyFlags) {
boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN;
int keyCode = event.getKeyCode();
+ mActiveInputDeviceId = event.getDeviceId();
+ InputDevice inputDevice = mInputManager.getInputDevice(mActiveInputDeviceId);
- if (!isMouseKey(keyCode)) {
+ if (!mDeviceKeyCodeMap.contains(mActiveInputDeviceId)) {
+ initializeDeviceToEnumMap(inputDevice);
+ }
+
+ if (!isMouseKey(keyCode, mActiveInputDeviceId)) {
// Pass non-mouse key events to the next handler
super.onKeyEvent(event, policyFlags);
} else if (isDown) {
- if (keyCode == MouseKeyEvent.SCROLL_TOGGLE.getKeyCodeValue()) {
+ if (keyCode == MouseKeyEvent.SCROLL_TOGGLE.getKeyCode(inputDevice)) {
mScrollToggleOn = !mScrollToggleOn;
if (DEBUG) {
Slog.d(LOG_TAG, "Scroll toggle " + (mScrollToggleOn ? "ON" : "OFF"));
}
- } else if (keyCode == MouseKeyEvent.HOLD.getKeyCodeValue()) {
+ } else if (keyCode == MouseKeyEvent.HOLD.getKeyCode(inputDevice)) {
sendVirtualMouseButtonEvent(
VirtualMouseButtonEvent.BUTTON_PRIMARY,
VirtualMouseButtonEvent.ACTION_BUTTON_PRESS
);
- } else if (keyCode == MouseKeyEvent.RELEASE.getKeyCodeValue()) {
+ } else if (keyCode == MouseKeyEvent.RELEASE.getKeyCode(inputDevice)) {
sendVirtualMouseButtonEvent(
VirtualMouseButtonEvent.BUTTON_PRIMARY,
VirtualMouseButtonEvent.ACTION_BUTTON_RELEASE
);
- } else if (isMouseButtonKey(keyCode)) {
+ } else if (isMouseButtonKey(keyCode, inputDevice)) {
performMouseButtonAction(keyCode);
- } else if (mScrollToggleOn && isMouseScrollKey(keyCode)) {
+ } else if (mScrollToggleOn && isMouseScrollKey(keyCode, inputDevice)) {
// If the scroll key is pressed down and no other key is active,
// set it as the active key and send a message to scroll the pointer
if (mActiveScrollKey == KEY_NOT_SET) {
@@ -439,7 +523,8 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
mHandler.removeMessages(MESSAGE_SCROLL_MOUSE_POINTER);
} else {
Slog.i(LOG_TAG, "Dropping event with key code: '" + keyCode
- + "', with no matching down event from deviceId = " + event.getDeviceId());
+ + "', with no matching down event from deviceId = "
+ + event.getDeviceId());
}
}
}
@@ -503,12 +588,40 @@ public class MouseKeysInterceptor extends BaseEventStreamTransformation
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@Override
public void onDestroy() {
- // Clear mouse state
- mActiveMoveKey = KEY_NOT_SET;
- mActiveScrollKey = KEY_NOT_SET;
- mLastTimeKeyActionPerformed = 0;
+ mHandler.post(() -> {
+ // Clear mouse state
+ mActiveMoveKey = KEY_NOT_SET;
+ mActiveScrollKey = KEY_NOT_SET;
+ mLastTimeKeyActionPerformed = 0;
+ mDeviceKeyCodeMap.clear();
+ });
mHandler.removeCallbacksAndMessages(null);
mVirtualDevice.close();
}
+
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
+ }
+
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ mDeviceKeyCodeMap.remove(deviceId);
+ }
+
+ /**
+ * The user can change the keyboard layout from settings at anytime, which would change
+ * key character map for that device. Hence, we should use this callback to
+ * update the key code to enum mapping if there is a change in the physical keyboard detected.
+ *
+ * @param deviceId The id of the input device that changed.
+ */
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ InputDevice inputDevice = mInputManager.getInputDevice(deviceId);
+ // Update the enum mapping only if input device that changed is a keyboard
+ if (inputDevice.isFullKeyboard() && !mDeviceKeyCodeMap.contains(deviceId)) {
+ initializeDeviceToEnumMap(inputDevice);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index e13b0a4a5440..3c574769eaec 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -299,7 +299,6 @@ import android.content.pm.TestUtilityService;
import android.content.pm.UserInfo;
import android.content.pm.UserProperties;
import android.content.pm.VersionedPackage;
-import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.ContentObserver;
@@ -2971,10 +2970,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- CompatibilityInfo compatibilityInfoForPackage(ApplicationInfo ai) {
- return mAtmInternal.compatibilityInfoForPackage(ai);
- }
-
/**
* Enforces that the uid that calls a method is not an
* {@link UserHandle#isIsolated(int) isolated} uid.
@@ -4635,7 +4630,6 @@ public class ActivityManagerService extends IActivityManager.Stub
ProtoLog.v(WM_DEBUG_CONFIGURATION, "Binding proc %s with config %s",
processName, app.getWindowProcessController().getConfiguration());
ApplicationInfo appInfo = instr != null ? instr.mTargetInfo : app.info;
- app.setCompat(compatibilityInfoForPackage(appInfo));
ProfilerInfo profilerInfo = mAppProfiler.setupProfilerInfoLocked(thread, app, instr);
@@ -4674,7 +4668,9 @@ public class ActivityManagerService extends IActivityManager.Stub
checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
bindApplicationTimeMillis = SystemClock.uptimeMillis();
bindApplicationTimeNanos = SystemClock.uptimeNanos();
- mAtmInternal.preBindApplication(app.getWindowProcessController());
+ final ActivityTaskManagerInternal.PreBindInfo preBindInfo =
+ mAtmInternal.preBindApplication(app.getWindowProcessController(), appInfo);
+ app.setCompat(preBindInfo.compatibilityInfo);
final ActiveInstrumentation instr2 = app.getActiveInstrumentation();
if (mPlatformCompat != null) {
mPlatformCompat.resetReporting(app.info);
@@ -4716,7 +4712,7 @@ public class ActivityManagerService extends IActivityManager.Stub
enableTrackAllocation,
isRestrictedBackupMode || !normalMode,
app.isPersistent(),
- new Configuration(app.getWindowProcessController().getConfiguration()),
+ preBindInfo.configuration,
app.getCompat(),
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 0e266f5644b6..7e3f613e383f 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1126,26 +1126,31 @@ public class OomAdjuster {
final int numLru = lruList.size();
if (mConstants.USE_TIERED_CACHED_ADJ) {
final long now = mInjector.getUptimeMillis();
+ int uiTargetAdj = 10;
for (int i = numLru - 1; i >= 0; i--) {
ProcessRecord app = lruList.get(i);
final ProcessStateRecord state = app.mState;
final ProcessCachedOptimizerRecord opt = app.mOptRecord;
- if (!app.isKilledByAm() && app.getThread() != null && state.getCurAdj()
- >= UNKNOWN_ADJ) {
+ if (!app.isKilledByAm() && app.getThread() != null
+ && (state.getCurAdj() >= UNKNOWN_ADJ
+ || (state.hasShownUi() && state.getCurAdj() >= CACHED_APP_MIN_ADJ))) {
final ProcessServiceRecord psr = app.mServices;
int targetAdj = CACHED_APP_MIN_ADJ;
if (opt != null && opt.isFreezeExempt()) {
// BIND_WAIVE_PRIORITY and the like get oom_adj 900
targetAdj += 0;
+ } else if (state.hasShownUi() && uiTargetAdj < 15) {
+ // The most recent 5 apps that have shown UI get 910-914
+ targetAdj += uiTargetAdj++;
} else if ((state.getSetAdj() >= CACHED_APP_MIN_ADJ)
&& (state.getLastStateTime()
+ mConstants.TIERED_CACHED_ADJ_DECAY_TIME) < now) {
// Older cached apps get 950
targetAdj += 50;
} else {
- // Newer cached apps get 910
- targetAdj += 10;
+ // Newer cached apps get 920
+ targetAdj += 20;
}
state.setCurRawAdj(targetAdj);
state.setCurAdj(psr.modifyRawOomAdj(targetAdj));
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index bdba6bcf66c0..b186eaacab74 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -1978,6 +1978,7 @@ class UserController implements Handler.Callback {
boolean userSwitchUiEnabled;
synchronized (mLock) {
mCurrentUserId = userId;
+ ActivityManager.invalidateGetCurrentUserIdCache();
userSwitchUiEnabled = mUserSwitchUiEnabled;
}
mInjector.updateUserConfiguration();
@@ -2239,6 +2240,7 @@ class UserController implements Handler.Callback {
return true;
}
mTargetUserId = targetUserId;
+ ActivityManager.invalidateGetCurrentUserIdCache();
userSwitchUiEnabled = mUserSwitchUiEnabled;
}
if (userSwitchUiEnabled) {
@@ -2316,6 +2318,7 @@ class UserController implements Handler.Callback {
synchronized (mLock) {
nextUserId = ObjectUtils.getOrElse(mPendingTargetUserIds.poll(), UserHandle.USER_NULL);
mTargetUserId = UserHandle.USER_NULL;
+ ActivityManager.invalidateGetCurrentUserIdCache();
}
if (nextUserId != UserHandle.USER_NULL) {
switchUser(nextUserId);
@@ -3021,6 +3024,9 @@ class UserController implements Handler.Callback {
mInjector.getUserManagerInternal().addUserLifecycleListener(mUserLifecycleListener);
updateProfileRelatedCaches();
mInjector.reportCurWakefulnessUsageEvent();
+
+ // IpcDataCache must be invalidated before it starts caching.
+ ActivityManager.invalidateGetCurrentUserIdCache();
}
// TODO(b/266158156): remove this method if initial system user boot logic is refactored?
@@ -3184,6 +3190,9 @@ class UserController implements Handler.Callback {
@GuardedBy("mLock")
private int getCurrentOrTargetUserIdLU() {
+ // Note: this result is currently cached by ActivityManager.getCurrentUser() - changes to
+ // the logic here may require updating how the cache is invalidated.
+ // See ActivityManager.invalidateGetCurrentUserIdCache() for more details.
return mTargetUserId != UserHandle.USER_NULL ? mTargetUserId : mCurrentUserId;
}
diff --git a/services/core/java/com/android/server/biometrics/PreAuthInfo.java b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
index eaf4f813d13a..ac3c02823d0a 100644
--- a/services/core/java/com/android/server/biometrics/PreAuthInfo.java
+++ b/services/core/java/com/android/server/biometrics/PreAuthInfo.java
@@ -120,7 +120,9 @@ class PreAuthInfo {
userId), trustManager)) {
isMandatoryBiometricsAuthentication = true;
promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG);
- promptInfo.setNegativeButtonText(context.getString(R.string.cancel));
+ if (promptInfo.getNegativeButtonText() == null) {
+ promptInfo.setNegativeButtonText(context.getString(R.string.cancel));
+ }
}
final boolean biometricRequested = Utils.isBiometricRequested(promptInfo);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 99ad65d14ff2..2b732eab67cc 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -269,6 +269,7 @@ public final class DisplayManagerService extends SystemService {
private final Context mContext;
private final DisplayManagerHandler mHandler;
+ private final HandlerExecutor mHandlerExecutor;
private final Handler mUiHandler;
private final DisplayModeDirector mDisplayModeDirector;
private final ExternalDisplayPolicy mExternalDisplayPolicy;
@@ -315,6 +316,7 @@ public final class DisplayManagerService extends SystemService {
public boolean mSafeMode;
// All callback records indexed by calling process id.
+ @GuardedBy("mSyncRoot")
private final SparseArray<CallbackRecord> mCallbacks = new SparseArray<>();
/**
@@ -354,7 +356,7 @@ public final class DisplayManagerService extends SystemService {
new CopyOnWriteArrayList<>();
/** All {@link DisplayPowerController}s indexed by {@link LogicalDisplay} ID. */
- private final SparseArray<DisplayPowerControllerInterface> mDisplayPowerControllers =
+ private final SparseArray<DisplayPowerController> mDisplayPowerControllers =
new SparseArray<>();
/** {@link DisplayBlanker} used by all {@link DisplayPowerController}s. */
@@ -602,6 +604,7 @@ public final class DisplayManagerService extends SystemService {
mContext = context;
mFlags = injector.getFlags();
mHandler = new DisplayManagerHandler(displayThreadLooper);
+ mHandlerExecutor = new HandlerExecutor(mHandler);
mUiHandler = UiThread.getHandler();
mDisplayDeviceRepo = new DisplayDeviceRepository(mSyncRoot, mPersistentDataStore);
mLogicalDisplayMapper = new LogicalDisplayMapper(mContext,
@@ -726,7 +729,7 @@ public final class DisplayManagerService extends SystemService {
if (logicalDisplay.getDisplayInfoLocked().type != Display.TYPE_INTERNAL) {
return;
}
- final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(
+ final DisplayPowerController dpc = mDisplayPowerControllers.get(
logicalDisplay.getDisplayIdLocked());
if (dpc == null) {
return;
@@ -760,12 +763,13 @@ public final class DisplayManagerService extends SystemService {
mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+
ActivityManager activityManager = mContext.getSystemService(ActivityManager.class);
activityManager.addOnUidImportanceListener(mUidImportanceListener, IMPORTANCE_CACHED);
mDeviceStateManager = LocalServices.getService(DeviceStateManagerInternal.class);
mContext.getSystemService(DeviceStateManager.class).registerCallback(
- new HandlerExecutor(mHandler), new DeviceStateListener());
+ mHandlerExecutor, new DeviceStateListener());
mLogicalDisplayMapper.onWindowManagerReady();
scheduleTraversalLocked(false);
@@ -1019,6 +1023,10 @@ public final class DisplayManagerService extends SystemService {
private class UidImportanceListener implements ActivityManager.OnUidImportanceListener {
@Override
public void onUidImportance(int uid, int importance) {
+ onUidImportanceInternal(uid, importance);
+ }
+
+ private void onUidImportanceInternal(int uid, int importance) {
synchronized (mPendingCallbackSelfLocked) {
if (importance >= IMPORTANCE_GONE) {
// Clean up as the app is already gone
@@ -2058,7 +2066,7 @@ public final class DisplayManagerService extends SystemService {
configurePreferredDisplayModeLocked(display);
}
- DisplayPowerControllerInterface dpc = addDisplayPowerControllerLocked(display);
+ DisplayPowerController dpc = addDisplayPowerControllerLocked(display);
if (dpc != null) {
final int leadDisplayId = display.getLeadDisplayIdLocked();
updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
@@ -2067,7 +2075,7 @@ public final class DisplayManagerService extends SystemService {
// that the follower display was added before the lead display.
mLogicalDisplayMapper.forEachLocked(d -> {
if (d.getLeadDisplayIdLocked() == displayId) {
- DisplayPowerControllerInterface followerDpc =
+ DisplayPowerController followerDpc =
mDisplayPowerControllers.get(d.getDisplayIdLocked());
if (followerDpc != null) {
updateDisplayPowerControllerLeaderLocked(followerDpc, displayId);
@@ -2151,7 +2159,7 @@ public final class DisplayManagerService extends SystemService {
scheduleTraversalLocked(false);
mPersistentDataStore.saveIfNeeded();
- DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+ DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
final int leadDisplayId = display.getLeadDisplayIdLocked();
updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
@@ -2165,7 +2173,7 @@ public final class DisplayManagerService extends SystemService {
}
private void updateDisplayPowerControllerLeaderLocked(
- @NonNull DisplayPowerControllerInterface dpc, int leadDisplayId) {
+ @NonNull DisplayPowerController dpc, int leadDisplayId) {
if (dpc.getLeadDisplayId() == leadDisplayId) {
// Lead display hasn't changed, nothing to do.
return;
@@ -2174,7 +2182,7 @@ public final class DisplayManagerService extends SystemService {
// If it has changed, then we need to unregister from the previous leader if there was one.
final int prevLeaderId = dpc.getLeadDisplayId();
if (prevLeaderId != Layout.NO_LEAD_DISPLAY) {
- final DisplayPowerControllerInterface prevLeader =
+ final DisplayPowerController prevLeader =
mDisplayPowerControllers.get(prevLeaderId);
if (prevLeader != null) {
prevLeader.removeDisplayBrightnessFollower(dpc);
@@ -2183,7 +2191,7 @@ public final class DisplayManagerService extends SystemService {
// And then, if it's following, register it with the new one.
if (leadDisplayId != Layout.NO_LEAD_DISPLAY) {
- final DisplayPowerControllerInterface newLeader =
+ final DisplayPowerController newLeader =
mDisplayPowerControllers.get(leadDisplayId);
if (newLeader != null) {
newLeader.addDisplayBrightnessFollower(dpc);
@@ -2224,7 +2232,7 @@ public final class DisplayManagerService extends SystemService {
private void releaseDisplayAndEmitEvent(LogicalDisplay display, int event) {
final int displayId = display.getDisplayIdLocked();
- final DisplayPowerControllerInterface dpc =
+ final DisplayPowerController dpc =
mDisplayPowerControllers.removeReturnOld(displayId);
if (dpc != null) {
updateDisplayPowerControllerLeaderLocked(dpc, Layout.NO_LEAD_DISPLAY);
@@ -2271,7 +2279,7 @@ public final class DisplayManagerService extends SystemService {
private void handleLogicalDisplayDeviceStateTransitionLocked(@NonNull LogicalDisplay display) {
final int displayId = display.getDisplayIdLocked();
- final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+ final DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
final int leadDisplayId = display.getLeadDisplayIdLocked();
updateDisplayPowerControllerLeaderLocked(dpc, leadDisplayId);
@@ -2692,14 +2700,14 @@ public final class DisplayManagerService extends SystemService {
if (userId != mCurrentUserId) {
return;
}
- DisplayPowerControllerInterface dpc = getDpcFromUniqueIdLocked(uniqueId);
+ DisplayPowerController dpc = getDpcFromUniqueIdLocked(uniqueId);
if (dpc != null) {
dpc.setBrightnessConfiguration(c, /* shouldResetShortTermModel= */ true);
}
}
}
- private DisplayPowerControllerInterface getDpcFromUniqueIdLocked(String uniqueId) {
+ private DisplayPowerController getDpcFromUniqueIdLocked(String uniqueId) {
final DisplayDevice displayDevice = mDisplayDeviceRepo.getByUniqueIdLocked(uniqueId);
final LogicalDisplay logicalDisplay = mLogicalDisplayMapper.getDisplayLocked(displayDevice);
if (logicalDisplay != null) {
@@ -2740,7 +2748,7 @@ public final class DisplayManagerService extends SystemService {
final BrightnessConfiguration config =
getBrightnessConfigForDisplayWithPdsFallbackLocked(uniqueId, userSerial);
if (config != null) {
- final DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(
+ final DisplayPowerController dpc = mDisplayPowerControllers.get(
logicalDisplay.getDisplayIdLocked());
if (dpc != null) {
dpc.setBrightnessConfiguration(config,
@@ -2987,7 +2995,7 @@ public final class DisplayManagerService extends SystemService {
void setAutoBrightnessLoggingEnabled(boolean enabled) {
synchronized (mSyncRoot) {
- final DisplayPowerControllerInterface displayPowerController =
+ final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
if (displayPowerController != null) {
displayPowerController.setAutoBrightnessLoggingEnabled(enabled);
@@ -2997,7 +3005,7 @@ public final class DisplayManagerService extends SystemService {
void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
synchronized (mSyncRoot) {
- final DisplayPowerControllerInterface displayPowerController =
+ final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
if (displayPowerController != null) {
displayPowerController.setDisplayWhiteBalanceLoggingEnabled(enabled);
@@ -3023,7 +3031,7 @@ public final class DisplayManagerService extends SystemService {
void setAmbientColorTemperatureOverride(float cct) {
synchronized (mSyncRoot) {
- final DisplayPowerControllerInterface displayPowerController =
+ final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(Display.DEFAULT_DISPLAY);
if (displayPowerController != null) {
displayPowerController.setAmbientColorTemperatureOverride(cct);
@@ -3033,7 +3041,7 @@ public final class DisplayManagerService extends SystemService {
void setDockedAndIdleEnabled(boolean enabled, int displayId) {
synchronized (mSyncRoot) {
- final DisplayPowerControllerInterface displayPowerController =
+ final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(displayId);
if (displayPowerController != null) {
displayPowerController.setAutomaticScreenBrightnessMode(enabled
@@ -3232,34 +3240,38 @@ public final class DisplayManagerService extends SystemService {
// After releasing the lock, send the notifications out.
for (int i = 0; i < mTempCallbacks.size(); i++) {
CallbackRecord callbackRecord = mTempCallbacks.get(i);
- final int uid = callbackRecord.mUid;
- final int pid = callbackRecord.mPid;
- if (isUidCached(uid)) {
- // For cached apps, save the pending event until it becomes non-cached
- synchronized (mPendingCallbackSelfLocked) {
- SparseArray<PendingCallback> pendingCallbacks = mPendingCallbackSelfLocked.get(
- uid);
- if (extraLogging(callbackRecord.mPackageName)) {
- Slog.i(TAG, "Uid is cached: " + uid
- + ", pendingCallbacks: " + pendingCallbacks);
- }
- if (pendingCallbacks == null) {
- pendingCallbacks = new SparseArray<>();
- mPendingCallbackSelfLocked.put(uid, pendingCallbacks);
- }
- PendingCallback pendingCallback = pendingCallbacks.get(pid);
- if (pendingCallback == null) {
- pendingCallbacks.put(pid,
- new PendingCallback(callbackRecord, displayId, event));
- } else {
- pendingCallback.addDisplayEvent(displayId, event);
- }
+ deliverEventInternal(callbackRecord, displayId, event);
+ }
+ mTempCallbacks.clear();
+ }
+
+ private void deliverEventInternal(CallbackRecord callbackRecord, int displayId, int event) {
+ final int uid = callbackRecord.mUid;
+ final int pid = callbackRecord.mPid;
+ if (isUidCached(uid)) {
+ // For cached apps, save the pending event until it becomes non-cached
+ synchronized (mPendingCallbackSelfLocked) {
+ SparseArray<PendingCallback> pendingCallbacks = mPendingCallbackSelfLocked.get(
+ uid);
+ if (extraLogging(callbackRecord.mPackageName)) {
+ Slog.i(TAG, "Uid is cached: " + uid
+ + ", pendingCallbacks: " + pendingCallbacks);
+ }
+ if (pendingCallbacks == null) {
+ pendingCallbacks = new SparseArray<>();
+ mPendingCallbackSelfLocked.put(uid, pendingCallbacks);
+ }
+ PendingCallback pendingCallback = pendingCallbacks.get(pid);
+ if (pendingCallback == null) {
+ pendingCallbacks.put(pid,
+ new PendingCallback(callbackRecord, displayId, event));
+ } else {
+ pendingCallback.addDisplayEvent(displayId, event);
}
- } else {
- callbackRecord.notifyDisplayEventAsync(displayId, event);
}
+ } else {
+ callbackRecord.notifyDisplayEventAsync(displayId, event);
}
- mTempCallbacks.clear();
}
private boolean extraLogging(String packageName) {
@@ -3571,7 +3583,7 @@ public final class DisplayManagerService extends SystemService {
}
@RequiresPermission(Manifest.permission.READ_DEVICE_CONFIG)
- private DisplayPowerControllerInterface addDisplayPowerControllerLocked(
+ private DisplayPowerController addDisplayPowerControllerLocked(
LogicalDisplay display) {
if (mPowerHandler == null) {
// initPowerManagement has not yet been called.
@@ -3585,7 +3597,7 @@ public final class DisplayManagerService extends SystemService {
final int userSerial = getUserManager().getUserSerialNumber(mContext.getUserId());
final BrightnessSetting brightnessSetting = new BrightnessSetting(userSerial,
mPersistentDataStore, display, mSyncRoot);
- final DisplayPowerControllerInterface displayPowerController;
+ final DisplayPowerController displayPowerController;
// If display is internal and has a HighBrightnessModeMetadata mapping, use that.
// Or create a new one and use that.
@@ -3764,7 +3776,7 @@ public final class DisplayManagerService extends SystemService {
public boolean mWifiDisplayScanRequested;
- CallbackRecord(int pid, int uid, IDisplayManagerCallback callback,
+ CallbackRecord(int pid, int uid, @NonNull IDisplayManagerCallback callback,
@EventsMask long eventsMask) {
mPid = pid;
mUid = uid;
@@ -3792,7 +3804,9 @@ public final class DisplayManagerService extends SystemService {
}
/**
- * @return {@code false} if RemoteException happens; otherwise {@code true} for success.
+ * @return {@code false} if RemoteException happens; otherwise {@code true} for
+ * success. This returns true even if the event was deferred because the remote client is
+ * cached.
*/
public boolean notifyDisplayEventAsync(int displayId, @DisplayEvent int event) {
if (!shouldSendEvent(event)) {
@@ -3805,9 +3819,19 @@ public final class DisplayManagerService extends SystemService {
"notifyDisplayEventAsync#notSendingEvent=" + event + ",mEventsMask="
+ mEventsMask);
}
+ // The client is not interested in this event, so do nothing.
return true;
}
+ return transmitDisplayEvent(displayId, event);
+ }
+
+ /**
+ * Transmit a single display event. The client is presumed ready. Return true on success
+ * and false if the client died.
+ */
+ private boolean transmitDisplayEvent(int displayId, @DisplayEvent int event) {
+ // The client is ready to receive the event.
try {
mCallback.onDisplayEvent(displayId, event);
return true;
@@ -3819,6 +3843,9 @@ public final class DisplayManagerService extends SystemService {
}
}
+ /**
+ * Return true if the client is interested in this event.
+ */
private boolean shouldSendEvent(@DisplayEvent int event) {
final long mask = mEventsMask.get();
switch (event) {
@@ -4373,7 +4400,7 @@ public final class DisplayManagerService extends SystemService {
uniqueId, userSerial);
if (config == null) {
// Get default configuration
- DisplayPowerControllerInterface dpc = getDpcFromUniqueIdLocked(uniqueId);
+ DisplayPowerController dpc = getDpcFromUniqueIdLocked(uniqueId);
if (dpc != null) {
config = dpc.getDefaultBrightnessConfiguration();
}
@@ -4427,7 +4454,7 @@ public final class DisplayManagerService extends SystemService {
if (display == null || !display.isEnabledLocked()) {
return null;
}
- DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+ DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
return dpc.getBrightnessInfo();
}
@@ -4472,7 +4499,7 @@ public final class DisplayManagerService extends SystemService {
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+ DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
dpc.setBrightness(brightness);
}
@@ -4492,7 +4519,7 @@ public final class DisplayManagerService extends SystemService {
final long token = Binder.clearCallingIdentity();
try {
synchronized (mSyncRoot) {
- DisplayPowerControllerInterface dpc = mDisplayPowerControllers.get(displayId);
+ DisplayPowerController dpc = mDisplayPowerControllers.get(displayId);
if (dpc != null) {
brightness = dpc.getScreenBrightnessSetting();
}
@@ -4819,7 +4846,7 @@ public final class DisplayManagerService extends SystemService {
id).getPrimaryDisplayDeviceLocked();
final int flags = displayDevice.getDisplayDeviceInfoLocked().flags;
if ((flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
- final DisplayPowerControllerInterface displayPowerController =
+ final DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(id);
if (displayPowerController != null) {
ready &= displayPowerController.requestPowerState(request,
@@ -5200,7 +5227,7 @@ public final class DisplayManagerService extends SystemService {
return null;
}
- DisplayPowerControllerInterface displayPowerController =
+ DisplayPowerController displayPowerController =
mDisplayPowerControllers.get(logicalDisplay.getDisplayIdLocked());
if (displayPowerController == null) {
Slog.w(TAG,
diff --git a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
index a188e79e4c8b..b05a96ea0439 100644
--- a/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
+++ b/services/core/java/com/android/server/display/DisplayOffloadSessionImpl.java
@@ -39,12 +39,12 @@ public class DisplayOffloadSessionImpl implements DisplayManagerInternal.Display
@Nullable
private final DisplayManagerInternal.DisplayOffloader mDisplayOffloader;
- private final DisplayPowerControllerInterface mDisplayPowerController;
+ private final DisplayPowerController mDisplayPowerController;
private boolean mIsActive;
public DisplayOffloadSessionImpl(
@Nullable DisplayManagerInternal.DisplayOffloader displayOffloader,
- DisplayPowerControllerInterface displayPowerController) {
+ DisplayPowerController displayPowerController) {
mDisplayOffloader = displayOffloader;
mDisplayPowerController = displayPowerController;
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index bf559c10b0ba..bb2bed7281f7 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -126,7 +126,7 @@ import java.util.Objects;
* slower by changing the "animator duration scale" option in Development Settings.
*/
final class DisplayPowerController implements AutomaticBrightnessController.Callbacks,
- DisplayWhiteBalanceController.Callbacks, DisplayPowerControllerInterface {
+ DisplayWhiteBalanceController.Callbacks{
private static final String SCREEN_ON_BLOCKED_TRACE_NAME = "Screen on blocked";
private static final String SCREEN_OFF_BLOCKED_TRACE_NAME = "Screen off blocked";
@@ -481,7 +481,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// DPCs following the brightness of this DPC. This is used in concurrent displays mode - there
// is one lead display, the additional displays follow the brightness value of the lead display.
@GuardedBy("mLock")
- private final SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers =
+ private final SparseArray<DisplayPowerController> mDisplayBrightnessFollowers =
new SparseArray();
private boolean mBootCompleted;
@@ -679,7 +679,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
/**
* Returns true if the proximity sensor screen-off function is available.
*/
- @Override
public boolean isProximitySensorAvailable() {
return mDisplayPowerProximityStateController.isProximitySensorAvailable();
}
@@ -691,7 +690,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
* @param includePackage if false will null out the package name in events
*/
@Nullable
- @Override
public ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(
@UserIdInt int userId, boolean includePackage) {
if (mBrightnessTracker == null) {
@@ -700,7 +698,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
return mBrightnessTracker.getEvents(userId, includePackage);
}
- @Override
public void onSwitchUser(@UserIdInt int newUserId, int userSerial, float newBrightness) {
Message msg = mHandler.obtainMessage(MSG_SWITCH_USER, newUserId, userSerial, newBrightness);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
@@ -737,7 +734,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
@Nullable
- @Override
public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(
@UserIdInt int userId) {
if (mBrightnessTracker == null) {
@@ -749,7 +745,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
/**
* Persist the brightness slider events and ambient brightness stats to disk.
*/
- @Override
public void persistBrightnessTrackerState() {
if (mBrightnessTracker != null) {
mBrightnessTracker.persistBrightnessTrackerState();
@@ -806,7 +801,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
- @Override
public void overrideDozeScreenState(int displayState, @Display.StateReason int reason) {
Slog.i(TAG, "New offload doze override: " + Display.stateToString(displayState));
if (mDisplayOffloadSession != null
@@ -833,7 +827,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
- @Override
public void setDisplayOffloadSession(DisplayOffloadSession session) {
if (session == mDisplayOffloadSession) {
return;
@@ -842,7 +835,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mDisplayOffloadSession = session;
}
- @Override
public BrightnessConfiguration getDefaultBrightnessConfiguration() {
if (mAutomaticBrightnessController == null) {
return null;
@@ -857,7 +849,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
*
* Make sure DisplayManagerService.mSyncRoot lock is held when this is called
*/
- @Override
public void onDisplayChanged(HighBrightnessModeMetadata hbmMetadata, int leadDisplayId) {
mLeadDisplayId = leadDisplayId;
final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked();
@@ -939,7 +930,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
* This method should be called when the DisplayPowerController is no longer in use; i.e. when
* the {@link #mDisplayId display} has been removed.
*/
- @Override
public void stop() {
synchronized (mLock) {
clearDisplayBrightnessFollowersLocked();
@@ -1216,7 +1206,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
- @Override
public void setAutomaticScreenBrightnessMode(
@AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
Message msg = mHandler.obtainMessage();
@@ -1314,7 +1303,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
boolean mustInitialize = false;
mBrightnessReasonTemp.set(null);
mTempBrightnessEvent.reset();
- SparseArray<DisplayPowerControllerInterface> displayBrightnessFollowers;
+ SparseArray<DisplayPowerController> displayBrightnessFollowers;
synchronized (mLock) {
if (mStopped) {
return;
@@ -1547,7 +1536,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
float ambientLux = mAutomaticBrightnessController == null ? 0
: mAutomaticBrightnessController.getAmbientLux();
for (int i = 0; i < displayBrightnessFollowers.size(); i++) {
- DisplayPowerControllerInterface follower = displayBrightnessFollowers.valueAt(i);
+ DisplayPowerController follower = displayBrightnessFollowers.valueAt(i);
follower.setBrightnessToFollow(rawBrightnessState,
mDisplayBrightnessController.convertToNits(rawBrightnessState),
ambientLux, slowChange);
@@ -1904,7 +1893,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
- @Override
public void updateBrightness() {
sendUpdatePowerState();
}
@@ -1913,12 +1901,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
* Ignores the proximity sensor until the sensor state changes, but only if the sensor is
* currently enabled and forcing the screen to be dark.
*/
- @Override
public void ignoreProximitySensorUntilChanged() {
mDisplayPowerProximityStateController.ignoreProximitySensorUntilChanged();
}
- @Override
public void setBrightnessConfiguration(BrightnessConfiguration c,
boolean shouldResetShortTermModel) {
Message msg = mHandler.obtainMessage(MSG_CONFIGURE_BRIGHTNESS,
@@ -1926,28 +1912,24 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
msg.sendToTarget();
}
- @Override
public void setTemporaryBrightness(float brightness) {
Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_BRIGHTNESS,
Float.floatToIntBits(brightness), 0 /*unused*/);
msg.sendToTarget();
}
- @Override
public void setTemporaryAutoBrightnessAdjustment(float adjustment) {
Message msg = mHandler.obtainMessage(MSG_SET_TEMPORARY_AUTO_BRIGHTNESS_ADJUSTMENT,
Float.floatToIntBits(adjustment), 0 /*unused*/);
msg.sendToTarget();
}
- @Override
public void setBrightnessFromOffload(float brightness) {
Message msg = mHandler.obtainMessage(MSG_SET_BRIGHTNESS_FROM_OFFLOAD,
Float.floatToIntBits(brightness), 0 /*unused*/);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
}
- @Override
public float[] getAutoBrightnessLevels(
@AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
int preset = Settings.System.getIntForUser(mContext.getContentResolver(),
@@ -1956,7 +1938,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
return mDisplayDeviceConfig.getAutoBrightnessBrighteningLevels(mode, preset);
}
- @Override
public float[] getAutoBrightnessLuxLevels(
@AutomaticBrightnessController.AutomaticBrightnessMode int mode) {
int preset = Settings.System.getIntForUser(mContext.getContentResolver(),
@@ -1965,7 +1946,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
return mDisplayDeviceConfig.getAutoBrightnessBrighteningLevelsLux(mode, preset);
}
- @Override
public BrightnessInfo getBrightnessInfo() {
synchronized (mCachedBrightnessInfo) {
return new BrightnessInfo(
@@ -1979,7 +1959,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
- @Override
public void onBootCompleted() {
Message msg = mHandler.obtainMessage(MSG_BOOT_COMPLETED);
mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
@@ -2495,18 +2474,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
-
- @Override
public float getScreenBrightnessSetting() {
return mDisplayBrightnessController.getScreenBrightnessSetting();
}
- @Override
public float getDozeBrightnessForOffload() {
return mDisplayBrightnessController.getCurrentBrightness() * mDozeScaleFactor;
}
- @Override
public void setBrightness(float brightness) {
// After HBMController and NBMController migration to Clampers framework
// currentBrightnessMax should be taken from clampers controller
@@ -2515,7 +2490,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mBrightnessRangeController.getCurrentBrightnessMax());
}
- @Override
public void setBrightness(float brightness, int userSerial) {
// After HBMController and NBMController migration to Clampers framework
// currentBrightnessMax should be taken from clampers controller
@@ -2524,17 +2498,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mBrightnessRangeController.getCurrentBrightnessMax());
}
- @Override
public int getDisplayId() {
return mDisplayId;
}
- @Override
public int getLeadDisplayId() {
return mLeadDisplayId;
}
- @Override
public void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux,
boolean slowChange) {
mBrightnessRangeController.onAmbientLuxChange(ambientLux);
@@ -2595,16 +2566,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mAutomaticBrightnessController.getLastSensorTimestamps());
}
- @Override
- public void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
+ public void addDisplayBrightnessFollower(DisplayPowerController follower) {
synchronized (mLock) {
mDisplayBrightnessFollowers.append(follower.getDisplayId(), follower);
sendUpdatePowerStateLocked();
}
}
- @Override
- public void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower) {
+ public void removeDisplayBrightnessFollower(DisplayPowerController follower) {
synchronized (mLock) {
mDisplayBrightnessFollowers.remove(follower.getDisplayId());
mHandler.postAtTime(() -> follower.setBrightnessToFollow(
@@ -2616,7 +2585,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
@GuardedBy("mLock")
private void clearDisplayBrightnessFollowersLocked() {
for (int i = 0; i < mDisplayBrightnessFollowers.size(); i++) {
- DisplayPowerControllerInterface follower = mDisplayBrightnessFollowers.valueAt(i);
+ DisplayPowerController follower = mDisplayBrightnessFollowers.valueAt(i);
mHandler.postAtTime(() -> follower.setBrightnessToFollow(
PowerManager.BRIGHTNESS_INVALID_FLOAT, BrightnessMappingStrategy.INVALID_NITS,
/* ambientLux= */ 0, /* slowChange= */ false), mClock.uptimeMillis());
@@ -2624,7 +2593,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mDisplayBrightnessFollowers.clear();
}
- @Override
public void dump(final PrintWriter pw) {
synchronized (mLock) {
pw.println();
@@ -3161,19 +3129,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
- @Override
public void setAutoBrightnessLoggingEnabled(boolean enabled) {
if (mAutomaticBrightnessController != null) {
mAutomaticBrightnessController.setLoggingEnabled(enabled);
}
}
- @Override // DisplayWhiteBalanceController.Callbacks
+ // DisplayWhiteBalanceController.Callbacks
public void updateWhiteBalance() {
sendUpdatePowerState();
}
- @Override
public void setDisplayWhiteBalanceLoggingEnabled(boolean enabled) {
Message msg = mHandler.obtainMessage();
msg.what = MSG_SET_DWBC_LOGGING_ENABLED;
@@ -3181,7 +3147,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
msg.sendToTarget();
}
- @Override
public void setAmbientColorTemperatureOverride(float cct) {
Message msg = mHandler.obtainMessage();
msg.what = MSG_SET_DWBC_COLOR_OVERRIDE;
diff --git a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
deleted file mode 100644
index d28578ad571f..000000000000
--- a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.display;
-
-import android.content.pm.ParceledListSlice;
-import android.hardware.display.AmbientBrightnessDayStats;
-import android.hardware.display.BrightnessChangeEvent;
-import android.hardware.display.BrightnessConfiguration;
-import android.hardware.display.BrightnessInfo;
-import android.hardware.display.DisplayManagerInternal;
-import android.os.PowerManager;
-import android.view.Display;
-
-import java.io.PrintWriter;
-
-/**
- * An interface to manage the display's power state and brightness
- */
-public interface DisplayPowerControllerInterface {
- /**
- * Notified when the display is changed.
- *
- * We use this to apply any changes that might be needed when displays get swapped on foldable
- * devices, when layouts change, etc.
- *
- * Must be called while holding the SyncRoot lock.
- *
- * @param hbmInfo The high brightness mode metadata, like
- * remaining time and hbm events, for the corresponding
- * physical display, to make sure we stay within the safety margins.
- * @param leadDisplayId The display who is considered our "leader" for things like brightness.
- */
- void onDisplayChanged(HighBrightnessModeMetadata hbmInfo, int leadDisplayId);
-
- /**
- * Unregisters all listeners and interrupts all running threads; halting future work.
- *
- * This method should be called when the DisplayPowerController is no longer in use; i.e. when
- * the display has been removed.
- */
- void stop();
-
- /**
- * Used to update the display's BrightnessConfiguration
- * @param config The new BrightnessConfiguration
- */
- void setBrightnessConfiguration(BrightnessConfiguration config,
- boolean shouldResetShortTermModel);
-
- /**
- * Used to set the ambient color temperature of the Display
- * @param ambientColorTemperature The target ambientColorTemperature
- */
- void setAmbientColorTemperatureOverride(float ambientColorTemperature);
-
- /**
- * Used to decide the associated AutomaticBrightnessController's BrightnessMode
- * @param mode The auto-brightness mode
- */
- void setAutomaticScreenBrightnessMode(
- @AutomaticBrightnessController.AutomaticBrightnessMode int mode);
-
- /**
- * Used to enable/disable the logging of the WhileBalance associated entities
- * @param enabled Flag which represents if the logging is the be enabled
- */
- void setDisplayWhiteBalanceLoggingEnabled(boolean enabled);
-
- /**
- * Used to dump the state.
- * @param writer The PrintWriter used to dump the state.
- */
- void dump(PrintWriter writer);
-
- /**
- * Used to get the ambient brightness stats
- */
- ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(int userId);
-
- /**
- * Get the default brightness configuration
- */
- BrightnessConfiguration getDefaultBrightnessConfiguration();
-
- /**
- * Set the screen brightness of the associated display
- * @param brightness The value to which the brightness is to be set
- */
- void setBrightness(float brightness);
-
- /**
- * Set the screen brightness of the associated display
- * @param brightness The value to which the brightness is to be set
- * @param userSerial The user for which the brightness value is to be set.
- */
- void setBrightness(float brightness, int userSerial);
-
- /**
- * Checks if the proximity sensor is available
- */
- boolean isProximitySensorAvailable();
-
- /**
- * Persist the brightness slider events and ambient brightness stats to disk.
- */
- void persistBrightnessTrackerState();
-
- /**
- * Ignores the proximity sensor until the sensor state changes, but only if the sensor is
- * currently enabled and forcing the screen to be dark.
- */
- void ignoreProximitySensorUntilChanged();
-
- /**
- * Requests a new power state.
- *
- * @param request The requested power state.
- * @param waitForNegativeProximity If true, issues a request to wait for
- * negative proximity before turning the screen back on,
- * assuming the screen was turned off by the proximity sensor.
- * @return True if display is ready, false if there are important changes that must
- * be made asynchronously.
- */
- boolean requestPowerState(DisplayManagerInternal.DisplayPowerRequest request,
- boolean waitForNegativeProximity);
-
- /**
- * Overrides the current doze screen state.
- *
- * @param displayState the new doze display state.
- * @param reason the reason behind the new doze display state.
- */
- void overrideDozeScreenState(int displayState, @Display.StateReason int reason);
-
- void setDisplayOffloadSession(DisplayManagerInternal.DisplayOffloadSession session);
-
- /**
- * Sets up the temporary autobrightness adjustment when the user is yet to settle down to a
- * value.
- */
- void setTemporaryAutoBrightnessAdjustment(float adjustment);
-
- /**
- * Sets temporary brightness from the offload chip until we get a brightness value from
- * the light sensor.
- * @param brightness The brightness value between {@link PowerManager.BRIGHTNESS_MIN} and
- * {@link PowerManager.BRIGHTNESS_MAX}. Values outside of that range will be ignored.
- */
- void setBrightnessFromOffload(float brightness);
-
- /**
- * Gets the screen brightness setting
- */
- float getScreenBrightnessSetting();
-
- /**
- * Gets the brightness value used when the device is in doze
- */
- float getDozeBrightnessForOffload();
-
- /**
- * Sets up the temporary brightness for the associated display
- */
- void setTemporaryBrightness(float brightness);
-
- /**
- * Gets the associated {@link BrightnessInfo}
- */
- BrightnessInfo getBrightnessInfo();
-
- /**
- * Get the {@link BrightnessChangeEvent}s for the specified user.
- */
- ParceledListSlice<BrightnessChangeEvent> getBrightnessEvents(int userId, boolean hasUsageStats);
-
- /**
- * Sets up the logging for the associated {@link AutomaticBrightnessController}
- * @param enabled Flag to represent if the logging is to be enabled
- */
- void setAutoBrightnessLoggingEnabled(boolean enabled);
-
- /**
- * Handles the changes to be done to update the brightness when the user is changed
- * @param newUserId The new userId
- * @param userSerial The serial number of the new user
- * @param newBrightness The brightness for the new user
- */
- void onSwitchUser(int newUserId, int userSerial, float newBrightness);
-
- /**
- * Get the ID of the display associated with this DPC.
- * @return The display ID
- */
- int getDisplayId();
-
- /**
- * Get the ID of the display that is the leader of this DPC.
- *
- * Note that this is different than the display associated with the DPC. The leader is another
- * display which we follow for things like brightness.
- *
- * Must be called while holding the SyncRoot lock.
- */
- int getLeadDisplayId();
-
- /**
- * Set the brightness to follow if this is an additional display in a set of concurrent
- * displays.
- * @param leadDisplayBrightness The brightness of the lead display in the set of concurrent
- * displays
- * @param nits The brightness value in nits if the device supports nits. Set to a negative
- * number otherwise.
- * @param ambientLux The lux value that will be passed to {@link HighBrightnessModeController}
- * @param slowChange Indicates whether we should slowly animate to the given brightness value.
- */
- void setBrightnessToFollow(float leadDisplayBrightness, float nits, float ambientLux,
- boolean slowChange);
-
- /**
- * Add an additional display that will copy the brightness value from this display. This is used
- * when the device is in concurrent displays mode.
- * @param follower The DPC that should copy the brightness value from this DPC
- */
- void addDisplayBrightnessFollower(DisplayPowerControllerInterface follower);
-
- /**
- * Removes the given display from the list of brightness followers.
- * @param follower The DPC to remove from the followers list
- */
- void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower);
-
- /**
- * Indicate that boot has been completed and the screen is ready to update.
- */
- void onBootCompleted();
-
- /**
- * Get the brightness levels used to determine automatic brightness based on lux levels.
- * @param mode The auto-brightness mode
- * @return The brightness levels for the specified mode. The values are between
- * {@link PowerManager.BRIGHTNESS_MIN} and {@link PowerManager.BRIGHTNESS_MAX}.
- */
- float[] getAutoBrightnessLevels(
- @AutomaticBrightnessController.AutomaticBrightnessMode int mode);
-
- /**
- * Get the lux levels used to determine automatic brightness.
- * @param mode The auto-brightness mode
- * @return The lux levels for the specified mode
- */
- float[] getAutoBrightnessLuxLevels(
- @AutomaticBrightnessController.AutomaticBrightnessMode int mode);
-}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 1220542af02a..52bf5379d367 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -597,9 +597,6 @@ public class InputManagerService extends IInputManager.Stub
mKeyRemapper.systemRunning();
mPointerIconCache.systemRunning();
mKeyboardGlyphManager.systemRunning();
- if (mTouchpadDebugViewController != null) {
- mTouchpadDebugViewController.systemRunning();
- }
}
private void reloadDeviceAliases() {
@@ -3340,6 +3337,13 @@ public class InputManagerService extends IInputManager.Stub
}
}
+ void updateTouchpadVisualizerEnabled(boolean enabled) {
+ mNative.setShouldNotifyTouchpadHardwareState(enabled);
+ if (mTouchpadDebugViewController != null) {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(enabled);
+ }
+ }
+
void updatePointerLocationEnabled(boolean enabled) {
mWindowManagerCallbacks.notifyPointerLocationChanged(enabled);
}
diff --git a/services/core/java/com/android/server/input/InputSettingsObserver.java b/services/core/java/com/android/server/input/InputSettingsObserver.java
index ef61d02cd999..835fb72e524a 100644
--- a/services/core/java/com/android/server/input/InputSettingsObserver.java
+++ b/services/core/java/com/android/server/input/InputSettingsObserver.java
@@ -180,7 +180,7 @@ class InputSettingsObserver extends ContentObserver {
}
private void updateTouchpadHardwareStateNotificationsEnabled() {
- mNative.setShouldNotifyTouchpadHardwareState(InputSettings.useTouchpadVisualizer(mContext));
+ mService.updateTouchpadVisualizerEnabled(InputSettings.useTouchpadVisualizer(mContext));
}
private void updateTouchpadRightClickZoneEnabled() {
diff --git a/services/core/java/com/android/server/input/debug/TouchpadDebugView.java b/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
index 5fca771c48b9..7785ffb4b17a 100644
--- a/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
+++ b/services/core/java/com/android/server/input/debug/TouchpadDebugView.java
@@ -16,23 +16,69 @@
package com.android.server.input.debug;
+import android.annotation.NonNull;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.util.Slog;
import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
-public class TouchpadDebugView extends LinearLayout {
+import java.util.Objects;
+public class TouchpadDebugView extends LinearLayout {
/**
* Input device ID for the touchpad that this debug view is displaying.
*/
private final int mTouchpadId;
+ @NonNull
+ private final WindowManager mWindowManager;
+
+ @NonNull
+ private final WindowManager.LayoutParams mWindowLayoutParams;
+
+ private final int mTouchSlop;
+
+ private float mTouchDownX;
+ private float mTouchDownY;
+ private int mScreenWidth;
+ private int mScreenHeight;
+ private int mWindowLocationBeforeDragX;
+ private int mWindowLocationBeforeDragY;
+
public TouchpadDebugView(Context context, int touchpadId) {
super(context);
mTouchpadId = touchpadId;
+ mWindowManager =
+ Objects.requireNonNull(getContext().getSystemService(WindowManager.class));
init(context);
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+
+ // TODO(b/360137366): Use the hardware properties to initialise layout parameters.
+ mWindowLayoutParams = new WindowManager.LayoutParams();
+ mWindowLayoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+ mWindowLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+ | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+ mWindowLayoutParams.privateFlags |=
+ WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
+ mWindowLayoutParams.setFitInsetsTypes(0);
+ mWindowLayoutParams.layoutInDisplayCutoutMode =
+ WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ mWindowLayoutParams.format = PixelFormat.TRANSLUCENT;
+ mWindowLayoutParams.setTitle("TouchpadDebugView - display " + mContext.getDisplayId());
+
+ mWindowLayoutParams.x = 40;
+ mWindowLayoutParams.y = 100;
+ mWindowLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
+ mWindowLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
+ mWindowLayoutParams.gravity = Gravity.TOP | Gravity.LEFT;
}
private void init(Context context) {
@@ -43,14 +89,12 @@ public class TouchpadDebugView extends LinearLayout {
setBackgroundColor(Color.TRANSPARENT);
// TODO(b/286551975): Replace this content with the touchpad debug view.
-
TextView textView1 = new TextView(context);
textView1.setBackgroundColor(Color.parseColor("#FFFF0000"));
textView1.setTextSize(20);
textView1.setText("Touchpad Debug View 1");
textView1.setGravity(Gravity.CENTER);
textView1.setTextColor(Color.WHITE);
-
textView1.setLayoutParams(new LayoutParams(1000, 200));
TextView textView2 = new TextView(context);
@@ -63,9 +107,98 @@ public class TouchpadDebugView extends LinearLayout {
addView(textView1);
addView(textView2);
+
+ updateScreenDimensions();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ float deltaX;
+ float deltaY;
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mWindowLocationBeforeDragX = mWindowLayoutParams.x;
+ mWindowLocationBeforeDragY = mWindowLayoutParams.y;
+ mTouchDownX = event.getRawX() - mWindowLocationBeforeDragX;
+ mTouchDownY = event.getRawY() - mWindowLocationBeforeDragY;
+ return true;
+
+ case MotionEvent.ACTION_MOVE:
+ deltaX = event.getRawX() - mWindowLayoutParams.x - mTouchDownX;
+ deltaY = event.getRawY() - mWindowLayoutParams.y - mTouchDownY;
+ Slog.d("TouchpadDebugView", "Slop = " + mTouchSlop);
+ if (isSlopExceeded(deltaX, deltaY)) {
+ Slog.d("TouchpadDebugView", "Slop exceeded");
+ mWindowLayoutParams.x =
+ Math.max(0, Math.min((int) (event.getRawX() - mTouchDownX),
+ mScreenWidth - this.getWidth()));
+ mWindowLayoutParams.y =
+ Math.max(0, Math.min((int) (event.getRawY() - mTouchDownY),
+ mScreenHeight - this.getHeight()));
+
+ Slog.d("TouchpadDebugView", "New position X: "
+ + mWindowLayoutParams.x + ", Y: " + mWindowLayoutParams.y);
+
+ mWindowManager.updateViewLayout(this, mWindowLayoutParams);
+ }
+ return true;
+
+ case MotionEvent.ACTION_UP:
+ deltaX = event.getRawX() - mWindowLayoutParams.x - mTouchDownX;
+ deltaY = event.getRawY() - mWindowLayoutParams.y - mTouchDownY;
+ if (!isSlopExceeded(deltaX, deltaY)) {
+ performClick();
+ }
+ return true;
+
+ case MotionEvent.ACTION_CANCEL:
+ // Move the window back to the original position
+ mWindowLayoutParams.x = mWindowLocationBeforeDragX;
+ mWindowLayoutParams.y = mWindowLocationBeforeDragY;
+ mWindowManager.updateViewLayout(this, mWindowLayoutParams);
+ return true;
+
+ default:
+ return super.onTouchEvent(event);
+ }
+ }
+
+ @Override
+ public boolean performClick() {
+ super.performClick();
+ Slog.d("TouchpadDebugView", "You clicked me!");
+ return true;
+ }
+
+ @Override
+ protected void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ updateScreenDimensions();
+
+ // Adjust view position to stay within screen bounds after rotation
+ mWindowLayoutParams.x =
+ Math.max(0, Math.min(mWindowLayoutParams.x, mScreenWidth - getWidth()));
+ mWindowLayoutParams.y =
+ Math.max(0, Math.min(mWindowLayoutParams.y, mScreenHeight - getHeight()));
+ mWindowManager.updateViewLayout(this, mWindowLayoutParams);
+ }
+
+ private boolean isSlopExceeded(float deltaX, float deltaY) {
+ return deltaX * deltaX + deltaY * deltaY >= mTouchSlop * mTouchSlop;
+ }
+
+ private void updateScreenDimensions() {
+ Rect windowBounds =
+ mWindowManager.getCurrentWindowMetrics().getBounds();
+ mScreenWidth = windowBounds.width();
+ mScreenHeight = windowBounds.height();
}
public int getTouchpadId() {
return mTouchpadId;
}
+
+ public WindowManager.LayoutParams getWindowLayoutParams() {
+ return mWindowLayoutParams;
+ }
}
diff --git a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
index c7760c63fec5..c28e74a02071 100644
--- a/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
+++ b/services/core/java/com/android/server/input/debug/TouchpadDebugViewController.java
@@ -18,14 +18,10 @@ package com.android.server.input.debug;
import android.annotation.Nullable;
import android.content.Context;
-import android.graphics.PixelFormat;
-import android.hardware.display.DisplayManager;
import android.hardware.input.InputManager;
import android.os.Handler;
import android.os.Looper;
import android.util.Slog;
-import android.view.Display;
-import android.view.Gravity;
import android.view.InputDevice;
import android.view.WindowManager;
@@ -34,58 +30,72 @@ import com.android.server.input.TouchpadHardwareProperties;
import java.util.Objects;
-public class TouchpadDebugViewController {
+public class TouchpadDebugViewController implements InputManager.InputDeviceListener {
- private static final String TAG = "TouchpadDebugViewController";
+ private static final String TAG = "TouchpadDebugView";
private final Context mContext;
private final Handler mHandler;
+
@Nullable
private TouchpadDebugView mTouchpadDebugView;
+
private final InputManagerService mInputManagerService;
+ private boolean mTouchpadVisualizerEnabled = false;
public TouchpadDebugViewController(Context context, Looper looper,
- InputManagerService inputManagerService) {
- final DisplayManager displayManager = Objects.requireNonNull(
- context.getSystemService(DisplayManager.class));
- final Display defaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
- mContext = context.createDisplayContext(defaultDisplay);
+ InputManagerService inputManagerService) {
+ //TODO(b/363979581): Handle multi-display scenarios
+ mContext = context;
mHandler = new Handler(looper);
mInputManagerService = inputManagerService;
}
- public void systemRunning() {
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
final InputManager inputManager = Objects.requireNonNull(
mContext.getSystemService(InputManager.class));
- inputManager.registerInputDeviceListener(mInputDeviceListener, mHandler);
- for (int deviceId : inputManager.getInputDeviceIds()) {
- mInputDeviceListener.onInputDeviceAdded(deviceId);
+ InputDevice inputDevice = inputManager.getInputDevice(deviceId);
+
+ if (Objects.requireNonNull(inputDevice).supportsSource(
+ InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE)
+ && mTouchpadVisualizerEnabled) {
+ showDebugView(deviceId);
}
}
- private final InputManager.InputDeviceListener mInputDeviceListener =
- new InputManager.InputDeviceListener() {
- @Override
- public void onInputDeviceAdded(int deviceId) {
- final InputManager inputManager = Objects.requireNonNull(
- mContext.getSystemService(InputManager.class));
- InputDevice inputDevice = inputManager.getInputDevice(deviceId);
-
- if (Objects.requireNonNull(inputDevice).supportsSource(
- InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE)) {
- showDebugView(deviceId);
- }
- }
-
- @Override
- public void onInputDeviceRemoved(int deviceId) {
- hideDebugView(deviceId);
- }
-
- @Override
- public void onInputDeviceChanged(int deviceId) {
- }
- };
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ hideDebugView(deviceId);
+ }
+
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ }
+
+ /**
+ * Notify the controller that the touchpad visualizer setting value has changed.
+ * This must be called from the same looper thread as {@code mHandler}.
+ */
+ public void updateTouchpadVisualizerEnabled(boolean touchpadVisualizerEnabled) {
+ if (mTouchpadVisualizerEnabled == touchpadVisualizerEnabled) {
+ return;
+ }
+ mTouchpadVisualizerEnabled = touchpadVisualizerEnabled;
+ final InputManager inputManager = Objects.requireNonNull(
+ mContext.getSystemService(InputManager.class));
+ if (touchpadVisualizerEnabled) {
+ inputManager.registerInputDeviceListener(this, mHandler);
+ for (int deviceId : inputManager.getInputDeviceIds()) {
+ onInputDeviceAdded(deviceId);
+ }
+ } else {
+ if (mTouchpadDebugView != null) {
+ hideDebugView(mTouchpadDebugView.getTouchpadId());
+ }
+ inputManager.unregisterInputDeviceListener(this);
+ }
+ }
private void showDebugView(int touchpadId) {
if (mTouchpadDebugView != null) {
@@ -95,32 +105,15 @@ public class TouchpadDebugViewController {
mContext.getSystemService(WindowManager.class));
mTouchpadDebugView = new TouchpadDebugView(mContext, touchpadId);
+ final WindowManager.LayoutParams mWindowLayoutParams =
+ mTouchpadDebugView.getWindowLayoutParams();
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
- lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
- lp.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
- | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
- lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
- lp.setFitInsetsTypes(0);
- lp.layoutInDisplayCutoutMode =
- WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
- lp.format = PixelFormat.TRANSLUCENT;
- lp.setTitle("TouchpadDebugView - display " + mContext.getDisplayId());
- lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL;
-
- lp.x = 40;
- lp.y = 100;
- lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
- lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
- lp.gravity = Gravity.TOP | Gravity.LEFT;
-
- wm.addView(mTouchpadDebugView, lp);
+ wm.addView(mTouchpadDebugView, mWindowLayoutParams);
Slog.d(TAG, "Touchpad debug view created.");
TouchpadHardwareProperties mTouchpadHardwareProperties =
mInputManagerService.getTouchpadHardwareProperties(
touchpadId);
- // TODO(b/360137366): Use the hardware properties to initialise layout parameters.
if (mTouchpadHardwareProperties != null) {
Slog.d(TAG, mTouchpadHardwareProperties.toString());
} else {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 7cfd2cc478a9..af0ccf93c826 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -350,13 +350,15 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl.
@BinderThread
private int resolveImeUserIdLocked(@UserIdInt int callingProcessUserId,
@NonNull IInputMethodClient client) {
- if (mConcurrentMultiUserModeEnabled
- && callingProcessUserId == UserHandle.USER_SYSTEM) {
- final var clientState = mClientController.getClient(client.asBinder());
- return mUserManagerInternal.getUserAssignedToDisplay(
- clientState.mSelfReportedDisplayId);
+ if (mConcurrentMultiUserModeEnabled) {
+ if (callingProcessUserId == UserHandle.USER_SYSTEM) {
+ final var clientState = mClientController.getClient(client.asBinder());
+ return mUserManagerInternal.getUserAssignedToDisplay(
+ clientState.mSelfReportedDisplayId);
+ }
+ return callingProcessUserId;
}
- return callingProcessUserId;
+ return mCurrentImeUserId;
}
/**
diff --git a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
index c8cb54f8a55e..bad959af7aad 100644
--- a/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
+++ b/services/core/java/com/android/server/notification/DefaultDeviceEffectsApplier.java
@@ -19,6 +19,9 @@ package com.android.server.notification;
import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_NIGHT;
import static android.app.UiModeManager.MODE_ATTENTION_THEME_OVERLAY_OFF;
+import static com.android.server.notification.ZenLog.traceApplyDeviceEffect;
+import static com.android.server.notification.ZenLog.traceScheduleApplyDeviceEffect;
+
import android.app.UiModeManager;
import android.app.WallpaperManager;
import android.content.BroadcastReceiver;
@@ -77,6 +80,8 @@ class DefaultDeviceEffectsApplier implements DeviceEffectsApplier {
if (mLastAppliedEffects.shouldSuppressAmbientDisplay()
!= effects.shouldSuppressAmbientDisplay()) {
try {
+ traceApplyDeviceEffect("suppressAmbientDisplay",
+ effects.shouldSuppressAmbientDisplay());
mPowerManager.suppressAmbientDisplay(SUPPRESS_AMBIENT_DISPLAY_TOKEN,
effects.shouldSuppressAmbientDisplay());
} catch (Exception e) {
@@ -87,6 +92,8 @@ class DefaultDeviceEffectsApplier implements DeviceEffectsApplier {
if (mLastAppliedEffects.shouldDisplayGrayscale() != effects.shouldDisplayGrayscale()) {
if (mColorDisplayManager != null) {
try {
+ traceApplyDeviceEffect("displayGrayscale",
+ effects.shouldDisplayGrayscale());
mColorDisplayManager.setSaturationLevel(
effects.shouldDisplayGrayscale() ? SATURATION_LEVEL_GRAYSCALE
: SATURATION_LEVEL_FULL_COLOR);
@@ -99,6 +106,7 @@ class DefaultDeviceEffectsApplier implements DeviceEffectsApplier {
if (mLastAppliedEffects.shouldDimWallpaper() != effects.shouldDimWallpaper()) {
if (mWallpaperManager != null) {
try {
+ traceApplyDeviceEffect("dimWallpaper", effects.shouldDimWallpaper());
mWallpaperManager.setWallpaperDimAmount(
effects.shouldDimWallpaper() ? WALLPAPER_DIM_AMOUNT_DIMMED
: WALLPAPER_DIM_AMOUNT_NORMAL);
@@ -134,6 +142,7 @@ class DefaultDeviceEffectsApplier implements DeviceEffectsApplier {
unregisterScreenOffReceiver();
updateNightModeImmediately(useNightMode);
} else {
+ traceScheduleApplyDeviceEffect("nightMode", useNightMode);
registerScreenOffReceiver();
}
}
@@ -150,6 +159,7 @@ class DefaultDeviceEffectsApplier implements DeviceEffectsApplier {
private void updateNightModeImmediately(boolean useNightMode) {
Binder.withCleanCallingIdentity(() -> {
try {
+ traceApplyDeviceEffect("nightMode", useNightMode);
mUiModeManager.setAttentionModeThemeOverlay(
useNightMode ? MODE_ATTENTION_THEME_OVERLAY_NIGHT
: MODE_ATTENTION_THEME_OVERLAY_OFF);
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index 1fdb57c0b61a..48b60b295791 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -75,7 +75,9 @@ import com.android.internal.util.XmlUtils;
import com.android.internal.util.function.TriPredicate;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
+import com.android.server.LocalServices;
import com.android.server.notification.NotificationManagerService.DumpFilter;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.utils.TimingsTraceAndSlog;
import org.xmlpull.v1.XmlPullParser;
@@ -134,6 +136,7 @@ abstract public class ManagedServices {
private final UserProfiles mUserProfiles;
protected final IPackageManager mPm;
protected final UserManager mUm;
+ private final UserManagerInternal mUserManagerInternal;
private final Config mConfig;
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -195,6 +198,7 @@ abstract public class ManagedServices {
mConfig = getConfig();
mApprovalLevel = APPROVAL_BY_COMPONENT;
mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+ mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
}
abstract protected Config getConfig();
@@ -1372,9 +1376,14 @@ abstract public class ManagedServices {
@GuardedBy("mMutex")
protected void populateComponentsToBind(SparseArray<Set<ComponentName>> componentsToBind,
final IntArray activeUsers,
- SparseArray<ArraySet<ComponentName>> approvedComponentsByUser) {
- mEnabledServicesForCurrentProfiles.clear();
- mEnabledServicesPackageNames.clear();
+ SparseArray<ArraySet<ComponentName>> approvedComponentsByUser,
+ boolean isVisibleBackgroundUser) {
+ // When it is a visible background user in Automotive MUMD environment,
+ // don't clear mEnabledServicesForCurrentProfile and mEnabledServicesPackageNames.
+ if (!isVisibleBackgroundUser) {
+ mEnabledServicesForCurrentProfiles.clear();
+ mEnabledServicesPackageNames.clear();
+ }
final int nUserIds = activeUsers.size();
for (int i = 0; i < nUserIds; ++i) {
@@ -1395,7 +1404,12 @@ abstract public class ManagedServices {
}
componentsToBind.put(userId, add);
-
+ // When it is a visible background user in Automotive MUMD environment,
+ // skip adding items to mEnabledServicesForCurrentProfile
+ // and mEnabledServicesPackageNames.
+ if (isVisibleBackgroundUser) {
+ continue;
+ }
mEnabledServicesForCurrentProfiles.addAll(userComponents);
for (int j = 0; j < userComponents.size(); j++) {
@@ -1443,7 +1457,10 @@ abstract public class ManagedServices {
IntArray userIds = mUserProfiles.getCurrentProfileIds();
boolean rebindAllCurrentUsers = mUserProfiles.isProfileUser(userToRebind, mContext)
&& allowRebindForParentUser();
+ boolean isVisibleBackgroundUser = false;
if (userToRebind != USER_ALL && !rebindAllCurrentUsers) {
+ isVisibleBackgroundUser =
+ mUserManagerInternal.isVisibleBackgroundFullUser(userToRebind);
userIds = new IntArray(1);
userIds.add(userToRebind);
}
@@ -1458,7 +1475,8 @@ abstract public class ManagedServices {
// Filter approvedComponentsByUser to collect all of the components that are allowed
// for the currently active user(s).
- populateComponentsToBind(componentsToBind, userIds, approvedComponentsByUser);
+ populateComponentsToBind(componentsToBind, userIds, approvedComponentsByUser,
+ isVisibleBackgroundUser);
// For every current non-system connection, disconnect services that are no longer
// approved, or ALL services if we are force rebinding
diff --git a/services/core/java/com/android/server/notification/ZenLog.java b/services/core/java/com/android/server/notification/ZenLog.java
index 82c5733655b0..1aa5ac046ae9 100644
--- a/services/core/java/com/android/server/notification/ZenLog.java
+++ b/services/core/java/com/android/server/notification/ZenLog.java
@@ -23,18 +23,15 @@ import android.net.Uri;
import android.os.Build;
import android.os.RemoteException;
import android.provider.Settings.Global;
-import android.service.notification.Condition;
import android.service.notification.IConditionProvider;
import android.service.notification.NotificationListenerService;
import android.service.notification.ZenModeConfig;
import android.service.notification.ZenModeDiff;
import android.util.LocalLog;
-import android.util.Log;
-import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
-import java.text.SimpleDateFormat;
-import java.util.Date;
import java.util.List;
public class ZenLog {
@@ -61,6 +58,8 @@ public class ZenLog {
private static final int TYPE_RECORD_CALLER = 19;
private static final int TYPE_CHECK_REPEAT_CALLER = 20;
private static final int TYPE_ALERT_ON_UPDATED_INTERCEPT = 21;
+ private static final int TYPE_APPLY_DEVICE_EFFECT = 22;
+ private static final int TYPE_SCHEDULE_APPLY_DEVICE_EFFECT = 23;
public static void traceIntercepted(NotificationRecord record, String reason) {
append(TYPE_INTERCEPTED, record.getKey() + "," + reason);
@@ -173,6 +172,14 @@ public class ZenLog {
+ ", given uri=" + hasUri);
}
+ public static void traceApplyDeviceEffect(String effect, boolean newValue) {
+ append(TYPE_APPLY_DEVICE_EFFECT, effect + " -> " + newValue);
+ }
+
+ public static void traceScheduleApplyDeviceEffect(String effect, boolean scheduledValue) {
+ append(TYPE_SCHEDULE_APPLY_DEVICE_EFFECT, effect + " -> " + scheduledValue);
+ }
+
private static String subscribeResult(IConditionProvider provider, RemoteException e) {
return provider == null ? "no provider" : e != null ? e.getMessage() : "ok";
}
@@ -196,6 +203,8 @@ public class ZenLog {
case TYPE_RECORD_CALLER: return "record_caller";
case TYPE_CHECK_REPEAT_CALLER: return "check_repeat_caller";
case TYPE_ALERT_ON_UPDATED_INTERCEPT: return "alert_on_updated_intercept";
+ case TYPE_APPLY_DEVICE_EFFECT: return "apply_device_effect";
+ case TYPE_SCHEDULE_APPLY_DEVICE_EFFECT: return "schedule_device_effect";
default: return "unknown";
}
}
@@ -273,4 +282,14 @@ public class ZenLog {
STATE_CHANGES.dump(prefix, pw);
}
}
+
+ @VisibleForTesting(/* otherwise = VisibleForTesting.NONE */)
+ public static void clear() {
+ synchronized (INTERCEPTION_EVENTS) {
+ INTERCEPTION_EVENTS.clear();
+ }
+ synchronized (STATE_CHANGES) {
+ STATE_CHANGES.clear();
+ }
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index d374142d3912..9fb9e717fe4d 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -42,6 +42,7 @@ import android.service.pm.PackageProto.UserInfoProto.ArchiveState.ArchiveActivit
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.IntArray;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
@@ -981,39 +982,23 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
}
int[] queryInstalledUsers(int[] users, boolean installed) {
- int num = 0;
+ IntArray installedUsers = new IntArray(users.length);
for (int user : users) {
if (getInstalled(user) == installed) {
- num++;
+ installedUsers.add(user);
}
}
- int[] res = new int[num];
- num = 0;
- for (int user : users) {
- if (getInstalled(user) == installed) {
- res[num] = user;
- num++;
- }
- }
- return res;
+ return installedUsers.toArray();
}
int[] queryUsersInstalledOrHasData(int[] users) {
- int num = 0;
- for (int user : users) {
- if (getInstalled(user) || readUserState(user).dataExists()) {
- num++;
- }
- }
- int[] res = new int[num];
- num = 0;
+ IntArray usersInstalledOrHasData = new IntArray(users.length);
for (int user : users) {
if (getInstalled(user) || readUserState(user).dataExists()) {
- res[num] = user;
- num++;
+ usersInstalledOrHasData.add(user);
}
}
- return res;
+ return usersInstalledOrHasData.toArray();
}
long getCeDataInode(int userId) {
@@ -1283,25 +1268,14 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
}
public int[] getNotInstalledUserIds() {
- int count = 0;
int userStateCount = mUserStates.size();
+ IntArray notInstalledUsers = new IntArray(userStateCount);
for (int i = 0; i < userStateCount; i++) {
if (!mUserStates.valueAt(i).isInstalled()) {
- count++;
- }
- }
- if (count == 0) {
- return EmptyArray.INT;
- }
-
- int[] excludedUserIds = new int[count];
- int idx = 0;
- for (int i = 0; i < userStateCount; i++) {
- if (!mUserStates.valueAt(i).isInstalled()) {
- excludedUserIds[idx++] = mUserStates.keyAt(i);
+ notInstalledUsers.add(mUserStates.keyAt(i));
}
}
- return excludedUserIds;
+ return notInstalledUsers.toArray();
}
/**
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index 26da84f99f5e..f9a8968b8ad6 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -292,8 +292,10 @@ final class RemovePackageHelper {
// Step 2: destroy app data.
mAppDataHelper.destroyAppDataLIF(resolvedPkg, userId, appDataDeletionFlags);
if (userId != UserHandle.USER_ALL) {
- ps.setCeDataInode(-1, userId);
- ps.setDeDataInode(-1, userId);
+ synchronized (mPm.mLock) {
+ ps.setCeDataInode(-1, userId);
+ ps.setDeDataInode(-1, userId);
+ }
}
final PreferredActivityHelper preferredActivityHelper = new PreferredActivityHelper(mPm,
@@ -425,19 +427,21 @@ final class RemovePackageHelper {
}
final boolean isArchive = (flags & PackageManager.DELETE_ARCHIVE) != 0;
final long currentTimeMillis = System.currentTimeMillis();
- for (int userId : outInfo.mRemovedUsers) {
- if (DEBUG_REMOVE) {
- final boolean wasInstalled = deletedPs.getInstalled(userId);
- Slog.d(TAG, " user " + userId + ": " + wasInstalled + " => " + false);
+ synchronized (mPm.mLock) {
+ for (int userId : outInfo.mRemovedUsers) {
+ if (DEBUG_REMOVE) {
+ final boolean wasInstalled = deletedPs.getInstalled(userId);
+ Slog.d(TAG, " user " + userId + ": " + wasInstalled + " => " + false);
+ }
+ deletedPs.setInstalled(/* installed= */ false, userId);
}
- deletedPs.setInstalled(/* installed= */ false, userId);
- }
- // Preserve split apk information for downgrade check with DELETE_KEEP_DATA and archived
- // app cases
- if (deletedPkg != null && deletedPkg.getSplitNames() != null) {
- deletedPs.setSplitNames(deletedPkg.getSplitNames());
- deletedPs.setSplitRevisionCodes(deletedPkg.getSplitRevisionCodes());
+ // Preserve split apk information for downgrade check with DELETE_KEEP_DATA and
+ // archived app cases
+ if (deletedPkg != null && deletedPkg.getSplitNames() != null) {
+ deletedPs.setSplitNames(deletedPkg.getSplitNames());
+ deletedPs.setSplitRevisionCodes(deletedPkg.getSplitRevisionCodes());
+ }
}
}
@@ -448,17 +452,19 @@ final class RemovePackageHelper {
if (DEBUG_REMOVE) {
Slog.d(TAG, "Propagating install state across downgrade");
}
- for (int userId : allUserHandles) {
- final boolean installed = ArrayUtils.contains(outInfo.mOrigUsers, userId);
- if (DEBUG_REMOVE) {
- Slog.d(TAG, " user " + userId + " => " + installed);
- }
- if (installed != deletedPs.getInstalled(userId)) {
- installedStateChanged = true;
- }
- deletedPs.setInstalled(installed, userId);
- if (installed) {
- deletedPs.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
+ synchronized (mPm.mLock) {
+ for (int userId : allUserHandles) {
+ final boolean installed = ArrayUtils.contains(outInfo.mOrigUsers, userId);
+ if (DEBUG_REMOVE) {
+ Slog.d(TAG, " user " + userId + " => " + installed);
+ }
+ if (installed != deletedPs.getInstalled(userId)) {
+ installedStateChanged = true;
+ }
+ deletedPs.setInstalled(installed, userId);
+ if (installed) {
+ deletedPs.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
+ }
}
}
}
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 6c78b3c85e18..6e7a009f58ce 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1366,7 +1366,7 @@ final class DefaultPermissionGrantPolicy {
for (int requestedPermissionNum = 0; requestedPermissionNum < numRequestedPermissions;
requestedPermissionNum++) {
- String permission = requestedPermissions[requestedPermissionNum];
+ String permission = sortedRequestedPermissions[requestedPermissionNum];
// If there is a disabled system app it may request a permission the updated
// version ot the data partition doesn't, In this case skip the permission.
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index f96706e474be..749025b0cf40 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -16,6 +16,7 @@
package com.android.server.policy;
+import static android.Manifest.permission.CREATE_VIRTUAL_DEVICE;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.Manifest.permission.OVERRIDE_SYSTEM_KEY_BEHAVIOR_IN_FOCUSED_WINDOW;
import static android.Manifest.permission.SYSTEM_ALERT_WINDOW;
@@ -59,13 +60,18 @@ import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_PRIVATE_PRESENTATION;
import static android.view.WindowManager.LayoutParams.TYPE_QS_DIALOG;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
+import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.LayoutParams.isSystemAlertWindowType;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_KEY_CHORD;
@@ -3058,7 +3064,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
@Override
public int checkAddPermission(int type, boolean isRoundedCornerOverlay, String packageName,
- int[] outAppOp) {
+ int[] outAppOp, int displayId) {
if (isRoundedCornerOverlay && mContext.checkCallingOrSelfPermission(INTERNAL_SYSTEM_WINDOW)
!= PERMISSION_GRANTED) {
return ADD_PERMISSION_DENIED;
@@ -3098,6 +3104,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_VOICE_INTERACTION:
case TYPE_QS_DIALOG:
case TYPE_NAVIGATION_BAR_PANEL:
+ case TYPE_STATUS_BAR:
+ case TYPE_NOTIFICATION_SHADE:
+ case TYPE_NAVIGATION_BAR:
+ case TYPE_STATUS_BAR_ADDITIONAL:
+ case TYPE_STATUS_BAR_SUB_PANEL:
+ case TYPE_VOICE_INTERACTION_STARTING:
// The window manager will check these.
return ADD_OKAY;
}
@@ -3141,6 +3153,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return ADD_OKAY;
}
+ // Allow virtual device owners to add overlays on the displays they own.
+ if (mWindowManagerFuncs.isCallerVirtualDeviceOwner(displayId, callingUid)
+ && mContext.checkCallingOrSelfPermission(CREATE_VIRTUAL_DEVICE)
+ == PERMISSION_GRANTED) {
+ return ADD_OKAY;
+ }
+
// check if user has enabled this operation. SecurityException will be thrown if this app
// has not been allowed by the user. The reason to use "noteOp" (instead of checkOp) is to
// make sure the usage is logged.
@@ -3581,18 +3600,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (down) {
int direction = keyCode == KeyEvent.KEYCODE_BRIGHTNESS_UP ? 1 : -1;
- // Disable autobrightness if it's on
- int auto = Settings.System.getIntForUser(
- mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS_MODE,
- Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
- UserHandle.USER_CURRENT_OR_SELF);
- if (auto != 0) {
- Settings.System.putIntForUser(mContext.getContentResolver(),
- Settings.System.SCREEN_BRIGHTNESS_MODE,
- Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL,
- UserHandle.USER_CURRENT_OR_SELF);
- }
int screenDisplayId = displayId < 0 ? DEFAULT_DISPLAY : displayId;
float minLinearBrightness = mPowerManager.getBrightnessConstraint(
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 989c8a802b36..892af6bec534 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -362,6 +362,12 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
* Invoked when a screenshot is taken of the given display to notify registered listeners.
*/
List<ComponentName> notifyScreenshotListeners(int displayId);
+
+ /**
+ * Returns whether the given UID is the owner of a virtual device, which the given display
+ * belongs to.
+ */
+ boolean isCallerVirtualDeviceOwner(int displayId, int callingUid);
}
/**
@@ -421,6 +427,7 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
* @param packageName package name
* @param outAppOp First element will be filled with the app op corresponding to
* this window, or OP_NONE.
+ * @param displayId The display on which this window is being added.
*
* @return {@link WindowManagerGlobal#ADD_OKAY} if the add can proceed;
* else an error code, usually
@@ -429,7 +436,7 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
* @see WindowManager.LayoutParams#PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY
*/
int checkAddPermission(int type, boolean isRoundedCornerOverlay, String packageName,
- int[] outAppOp);
+ int[] outAppOp, int displayId);
/**
* After the window manager has computed the current configuration based
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 822ec2eb79b0..6847a5c699ac 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -54,6 +54,7 @@ import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.Temperature;
+import android.os.Trace;
import android.util.ArrayMap;
import android.util.EventLog;
import android.util.Slog;
@@ -247,6 +248,7 @@ public class ThermalManagerService extends SystemService {
private void setStatusLocked(int newStatus) {
if (newStatus != mStatus) {
+ Trace.traceCounter(Trace.TRACE_TAG_POWER, "ThermalManagerService.status", newStatus);
mStatus = newStatus;
notifyStatusListenersLocked();
}
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 67900f843063..60b5e658dfc5 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -3306,7 +3306,20 @@ public final class TvInputManagerService extends SystemService {
return filteredDisplayName;
}
- private static final class UserState {
+ private class TvInputManagerCallbackList extends RemoteCallbackList<ITvInputManagerCallback> {
+ @Override
+ public void onCallbackDied(ITvInputManagerCallback callback) {
+ synchronized (mLock) {
+ for (int i = 0; i < mUserStates.size(); i++) {
+ int userId = mUserStates.keyAt(i);
+ UserState userState = getOrCreateUserStateLocked(userId);
+ userState.callbackPidUidMap.remove(callback);
+ }
+ }
+ }
+ }
+
+ private final class UserState {
// A mapping from the TV input id to its TvInputState.
private Map<String, TvInputState> inputMap = new HashMap<>();
@@ -3327,8 +3340,8 @@ public final class TvInputManagerService extends SystemService {
private final Map<IBinder, SessionState> sessionStateMap = new HashMap<>();
// A list of callbacks.
- private final RemoteCallbackList<ITvInputManagerCallback> mCallbacks =
- new RemoteCallbackList<>();
+ private final TvInputManagerCallbackList mCallbacks =
+ new TvInputManagerCallbackList();
private final Map<ITvInputManagerCallback, Pair<Integer, Integer>> callbackPidUidMap =
new HashMap<>();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index 26a6b00254d3..b8ce02ed5937 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -380,7 +380,16 @@ public abstract class ActivityTaskManagerInternal {
public abstract void onPackageAdded(String name, boolean replacing);
public abstract void onPackageReplaced(ApplicationInfo aInfo);
- public abstract CompatibilityInfo compatibilityInfoForPackage(ApplicationInfo ai);
+ /** The data for IApplicationThread#bindApplication. */
+ public static final class PreBindInfo {
+ public final @NonNull CompatibilityInfo compatibilityInfo;
+ public final @NonNull Configuration configuration;
+
+ PreBindInfo(@NonNull CompatibilityInfo compatInfo, @NonNull Configuration config) {
+ compatibilityInfo = compatInfo;
+ configuration = config;
+ }
+ }
public final class ActivityTokens {
private final @NonNull IBinder mActivityToken;
@@ -502,7 +511,9 @@ public abstract class ActivityTaskManagerInternal {
public abstract void resumeTopActivities(boolean scheduleIdle);
/** Called by AM just before it binds to an application process. */
- public abstract void preBindApplication(WindowProcessController wpc);
+ @NonNull
+ public abstract PreBindInfo preBindApplication(@NonNull WindowProcessController wpc,
+ @NonNull ApplicationInfo info);
/** Called by AM when an application process attaches. */
public abstract boolean attachApplication(WindowProcessController wpc) throws RemoteException;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 3cfb9a07e941..e25d940d9781 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -6428,13 +6428,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
- public CompatibilityInfo compatibilityInfoForPackage(ApplicationInfo ai) {
- synchronized (mGlobalLock) {
- return compatibilityInfoForPackageLocked(ai);
- }
- }
-
- @Override
public void sendActivityResult(int callingUid, IBinder activityToken, String resultWho,
int requestCode, int resultCode, Intent data) {
final ActivityRecord r;
@@ -6712,9 +6705,13 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
- public void preBindApplication(WindowProcessController wpc) {
+ public PreBindInfo preBindApplication(WindowProcessController wpc, ApplicationInfo info) {
synchronized (mGlobalLockWithoutBoost) {
mTaskSupervisor.getActivityMetricsLogger().notifyBindApplication(wpc.mInfo);
+ wpc.onConfigurationChanged(getGlobalConfiguration());
+ // The "info" can be the target of instrumentation.
+ return new PreBindInfo(compatibilityInfoForPackageLocked(info),
+ new Configuration(wpc.getConfiguration()));
}
}
@@ -7481,9 +7478,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
FEATURE_LEANBACK);
final boolean isArc = arcFeature != null && arcFeature.version >= 0;
final boolean isTv = tvFeature != null && tvFeature.version >= 0;
- sIsPip2ExperimentEnabled = SystemProperties.getBoolean(
- "persist.wm_shell.pip2", false)
- || (Flags.enablePip2Implementation() && !isArc && !isTv);
+ sIsPip2ExperimentEnabled = Flags.enablePip2() && !isArc && !isTv;
}
return sIsPip2ExperimentEnabled;
}
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index e90a2c90bfab..9a3ad2d85de6 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -107,7 +107,6 @@ import android.app.servertransaction.LaunchActivityItem;
import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.ResumeActivityItem;
import android.app.servertransaction.StopActivityItem;
-import android.companion.virtual.VirtualDeviceManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -158,6 +157,7 @@ import com.android.server.LocalServices;
import com.android.server.am.ActivityManagerService;
import com.android.server.am.HostingRecord;
import com.android.server.am.UserState;
+import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
import com.android.server.pm.SaferIntentUtils;
import com.android.server.utils.Slogf;
import com.android.server.wm.ActivityMetricsLogger.LaunchingState;
@@ -285,7 +285,7 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
private WindowManagerService mWindowManager;
private AppOpsManager mAppOpsManager;
- private VirtualDeviceManager mVirtualDeviceManager;
+ private VirtualDeviceManagerInternal mVirtualDeviceManagerInternal;
/** Common synchronization logic used to save things to disks. */
PersisterQueue mPersisterQueue;
@@ -1298,16 +1298,24 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
if (displayId == DEFAULT_DISPLAY || displayId == INVALID_DISPLAY) {
return Context.DEVICE_ID_DEFAULT;
}
- if (mVirtualDeviceManager == null) {
+ if (mVirtualDeviceManagerInternal == null) {
if (mService.mHasCompanionDeviceSetupFeature) {
- mVirtualDeviceManager =
- mService.mContext.getSystemService(VirtualDeviceManager.class);
+ mVirtualDeviceManagerInternal =
+ LocalServices.getService(VirtualDeviceManagerInternal.class);
}
- if (mVirtualDeviceManager == null) {
+ if (mVirtualDeviceManagerInternal == null) {
return Context.DEVICE_ID_DEFAULT;
}
}
- return mVirtualDeviceManager.getDeviceIdForDisplayId(displayId);
+ return mVirtualDeviceManagerInternal.getDeviceIdForDisplayId(displayId);
+ }
+
+ boolean isDeviceOwnerUid(int displayId, int callingUid) {
+ final int deviceId = getDeviceIdForDisplayId(displayId);
+ if (deviceId == Context.DEVICE_ID_DEFAULT || deviceId == Context.DEVICE_ID_INVALID) {
+ return false;
+ }
+ return mVirtualDeviceManagerInternal.getDeviceOwnerUid(deviceId) == callingUid;
}
private AppOpsManager getAppOpsManager() {
diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java
index 28dbc3a664a5..4e4616dcaa3f 100644
--- a/services/core/java/com/android/server/wm/BackNavigationController.java
+++ b/services/core/java/com/android/server/wm/BackNavigationController.java
@@ -339,13 +339,12 @@ class BackNavigationController {
removedWindowContainer,
BackNavigationInfo.typeToString(backType));
- // For now, we only animate when going home, cross task or cross-activity.
boolean prepareAnimation =
(backType == BackNavigationInfo.TYPE_RETURN_TO_HOME
|| backType == BackNavigationInfo.TYPE_CROSS_TASK
|| backType == BackNavigationInfo.TYPE_CROSS_ACTIVITY
|| backType == BackNavigationInfo.TYPE_DIALOG_CLOSE)
- && adapter != null;
+ && (adapter != null && adapter.isAnimatable(backType));
if (prepareAnimation) {
final AnimationHandler.ScheduleAnimationBuilder builder =
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d495acb5896e..97d35b90ef3c 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3212,15 +3212,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
* If xPpi or yDpi is equal to {@link #INVALID_DPI}, the values are ignored.
*/
void setForcedSize(int width, int height, float xDPI, float yDPI) {
- // Can't force size higher than the maximal allowed
- if (mMaxUiWidth > 0 && width > mMaxUiWidth) {
- final float ratio = mMaxUiWidth / (float) width;
- height = (int) (height * ratio);
- width = mMaxUiWidth;
- }
-
mIsSizeForced = mInitialDisplayWidth != width || mInitialDisplayHeight != height;
if (mIsSizeForced) {
+ if (mMaxUiWidth > 0 && width > mMaxUiWidth) {
+ final float ratio = mMaxUiWidth / (float) width;
+ height = (int) (height * ratio);
+ width = mMaxUiWidth;
+ }
final Point size = getValidForcedSize(width, height);
width = size.x;
height = size.y;
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 745b79209546..5c621208c4db 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1036,7 +1036,7 @@ public class DisplayPolicy {
/**
* Check if a window can be added to the system.
*
- * Currently enforces that two window types are singletons per display:
+ * Currently enforces that these window types are singletons per display:
* <ul>
* <li>{@link WindowManager.LayoutParams#TYPE_STATUS_BAR}</li>
* <li>{@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}</li>
@@ -1058,41 +1058,39 @@ public class DisplayPolicy {
ActivityTaskManagerService.enforceTaskPermission("DisplayPolicy");
}
+ final String systemUiPermission =
+ mService.isCallerVirtualDeviceOwner(mDisplayContent.getDisplayId(), callingUid)
+ // Allow virtual device owners to add system windows on their displays.
+ ? android.Manifest.permission.CREATE_VIRTUAL_DEVICE
+ : android.Manifest.permission.STATUS_BAR_SERVICE;
+
switch (attrs.type) {
case TYPE_STATUS_BAR:
- mContext.enforcePermission(
- android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+ mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
"DisplayPolicy");
if (mStatusBar != null && mStatusBar.isAlive()) {
return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
break;
case TYPE_NOTIFICATION_SHADE:
- mContext.enforcePermission(
- android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+ mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
"DisplayPolicy");
- if (mNotificationShade != null) {
- if (mNotificationShade.isAlive()) {
- return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
- }
+ if (mNotificationShade != null && mNotificationShade.isAlive()) {
+ return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
break;
case TYPE_NAVIGATION_BAR:
- mContext.enforcePermission(android.Manifest.permission.STATUS_BAR_SERVICE,
- callingPid, callingUid, "DisplayPolicy");
+ mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
+ "DisplayPolicy");
if (mNavigationBar != null && mNavigationBar.isAlive()) {
return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
break;
case TYPE_NAVIGATION_BAR_PANEL:
- mContext.enforcePermission(android.Manifest.permission.STATUS_BAR_SERVICE,
- callingPid, callingUid, "DisplayPolicy");
- break;
case TYPE_STATUS_BAR_ADDITIONAL:
case TYPE_STATUS_BAR_SUB_PANEL:
case TYPE_VOICE_INTERACTION_STARTING:
- mContext.enforcePermission(
- android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+ mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
"DisplayPolicy");
break;
case TYPE_STATUS_BAR_PANEL:
@@ -1102,8 +1100,7 @@ public class DisplayPolicy {
if (attrs.providedInsets != null) {
// Recents component is allowed to add inset types.
if (!mService.mAtmService.isCallerRecents(callingUid)) {
- mContext.enforcePermission(
- android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
+ mContext.enforcePermission(systemUiPermission, callingPid, callingUid,
"DisplayPolicy");
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index f40f26179f85..e585efa8a3cc 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -69,6 +69,7 @@ class DisplayWindowSettings {
mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings);
}
+ /** Stores the size override settings. If the width or height is zero, it means to clear. */
void setForcedSize(@NonNull DisplayContent displayContent, int width, int height) {
if (displayContent.isDefaultDisplay) {
final String sizeString = (width == 0 || height == 0) ? "" : (width + "," + height);
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 90b9a0452eb1..fb57a1bb94c1 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1524,7 +1524,7 @@ public class WindowManagerService extends IWindowManager.Stub
final boolean isRoundedCornerOverlay = (attrs.privateFlags
& PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0;
int res = mPolicy.checkAddPermission(attrs.type, isRoundedCornerOverlay, attrs.packageName,
- appOp);
+ appOp, displayId);
if (res != ADD_OKAY) {
return res;
}
@@ -6023,7 +6023,7 @@ public class WindowManagerService extends IWindowManager.Stub
displayContent.setForcedSize(displayContent.mInitialDisplayWidth,
displayContent.mInitialDisplayHeight,
displayContent.mInitialPhysicalXDpi,
- displayContent.mInitialPhysicalXDpi);
+ displayContent.mInitialPhysicalYDpi);
}
}
} finally {
@@ -10121,6 +10121,23 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ /**
+ * Returns whether the given UID is the owner of a virtual device, which the given display
+ * belongs to.
+ */
+ @Override
+ public boolean isCallerVirtualDeviceOwner(int displayId, int callingUid) {
+ if (!android.companion.virtualdevice.flags.Flags.statusBarAndInsets()) {
+ return false;
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ return mAtmService.mTaskSupervisor.isDeviceOwnerUid(displayId, callingUid);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
@RequiresPermission(ACCESS_SURFACE_FLINGER)
@Override
public boolean replaceContentOnDisplay(int displayId, SurfaceControl sc) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index b6b36c716a53..87ce8661c97c 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -358,7 +358,6 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
mUseFifoUiScheduling = com.android.window.flags.Flags.fifoPriorityForMajorUiProcesses()
&& (isSysUiPackage || mAtm.isCallerRecents(uid));
- onConfigurationChanged(atm.getGlobalConfiguration());
mAtm.mPackageConfigPersister.updateConfigIfNeeded(this, mUserId, mInfo.packageName);
}
@@ -1926,7 +1925,12 @@ public class WindowProcessController extends ConfigurationContainer<Configuratio
// showing.
// If the configuration has been overridden by previous activity, empty it.
mIsActivityConfigOverrideAllowed = false;
- unregisterActivityConfigurationListener();
+ // The call to `onServiceStarted` is not guarded with WM lock.
+ mAtm.mH.post(() -> {
+ synchronized (mAtm.mGlobalLock) {
+ unregisterActivityConfigurationListener();
+ }
+ });
break;
default:
break;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index fc619677bb56..470025a67dee 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -7151,9 +7151,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// If there is a profile owner, redirect to that; otherwise query the device owner.
ComponentName aliasChooser = getProfileOwnerAsUser(caller.getUserId());
- boolean isDoUser = Flags.headlessSingleUserFixes()
- ? caller.getUserId() == getDeviceOwnerUserId()
- : caller.getUserHandle().isSystem();
+ boolean isDoUser = caller.getUserId() == getDeviceOwnerUserId();
if (aliasChooser == null && isDoUser) {
synchronized (getLockObject()) {
final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked();
@@ -8163,7 +8161,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// First check whether the admin is allowed to wipe the device/user/profile.
final String restriction;
boolean shouldFactoryReset = userId == UserHandle.USER_SYSTEM;
- if (Flags.headlessSingleUserFixes() && getHeadlessDeviceOwnerModeForDeviceOwner()
+ if (getHeadlessDeviceOwnerModeForDeviceOwner()
== HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER) {
shouldFactoryReset = userId == getMainUserId();
}
@@ -8187,8 +8185,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
adminPackage,
userId)) {
// Legacy mode
- wipeDevice = Flags.headlessSingleUserFixes()
- && getHeadlessDeviceOwnerModeForDeviceOwner()
+ wipeDevice = getHeadlessDeviceOwnerModeForDeviceOwner()
== HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER ? isMainUser : isSystemUser;
} else {
// Explicit behaviour
@@ -11858,7 +11855,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
setBackwardsCompatibleAppRestrictions(
caller, packageName, restrictions, caller.getUserHandle());
- } else if (Flags.dmrhSetAppRestrictions()) {
+ } else {
final boolean isRoleHolder;
if (who != null) {
// DO or PO
@@ -11905,15 +11902,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
caller.getUserHandle());
});
}
- } else {
- Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
- || (caller.hasPackage() && isCallerDelegate(caller,
- DELEGATION_APP_RESTRICTIONS)));
- mInjector.binderWithCleanCallingIdentity(() -> {
- mUserManager.setApplicationRestrictions(packageName, restrictions,
- caller.getUserHandle());
- });
}
DevicePolicyEventLogger
@@ -13244,7 +13232,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return Bundle.EMPTY;
}
return policies.get(enforcingAdmin).getValue();
- } else if (Flags.dmrhSetAppRestrictions()) {
+ } else {
final boolean isRoleHolder;
if (who != null) {
// Caller is DO or PO. They cannot call this on parent
@@ -13287,19 +13275,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return bundle != null ? bundle : Bundle.EMPTY;
});
}
-
- } else {
- Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
- || (caller.hasPackage() && isCallerDelegate(caller,
- DELEGATION_APP_RESTRICTIONS)));
- return mInjector.binderWithCleanCallingIdentity(() -> {
- Bundle bundle = mUserManager.getApplicationRestrictions(packageName,
- caller.getUserHandle());
- // if no restrictions were saved, mUserManager.getApplicationRestrictions
- // returns null, but DPM method should return an empty Bundle as per JavaDoc
- return bundle != null ? bundle : Bundle.EMPTY;
- });
}
}
@@ -18662,8 +18637,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
// Backup service has to be enabled on the main user in order for it to be enabled on
// secondary users.
- if (Flags.headlessSingleUserFixes() && isDeviceOwner(caller)
- && getHeadlessDeviceOwnerModeForDeviceOwner()
+ if (isDeviceOwner(caller) && getHeadlessDeviceOwnerModeForDeviceOwner()
== HEADLESS_DEVICE_OWNER_MODE_SINGLE_USER) {
toggleBackupServiceActive(UserHandle.USER_SYSTEM, enabled);
}
diff --git a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
index 7ed23cd7df3e..d2c91ff2ef60 100644
--- a/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
+++ b/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt
@@ -888,7 +888,7 @@ class AppIdPermissionPolicy : SchemePolicy() {
val mayGrantByPrivileged =
!permission.isPrivileged ||
requestingPackageStates.anyIndexed { _, it ->
- checkPrivilegedPermissionAllowlist(it, permission)
+ checkPrivilegedPermissionAllowlistIfNeeded(it, permission)
}
val shouldGrantBySignature =
permission.isSignature &&
@@ -1280,7 +1280,16 @@ class AppIdPermissionPolicy : SchemePolicy() {
}
}
- private fun MutateStateScope.checkPrivilegedPermissionAllowlist(
+ /**
+ * We only check privileged permission allowlist for system privileged apps. Hence, for platform
+ * or for normal apps, we return true to indicate that we don't need to check the allowlist and
+ * will let follow-up checks to decide whether we should grant the permission.
+ *
+ * @return `true`, if the permission is allowlisted for system privileged apps, or if we
+ * don't need to check the allowlist (for platform or for normal apps).
+ * `false`, if the permission is not allowlisted for system privileged apps.
+ */
+ private fun MutateStateScope.checkPrivilegedPermissionAllowlistIfNeeded(
packageState: PackageState,
permission: Permission
): Boolean {
diff --git a/services/tests/InputMethodSystemServerTests/Android.bp b/services/tests/InputMethodSystemServerTests/Android.bp
index 3bce9b54e320..9044259cb39f 100644
--- a/services/tests/InputMethodSystemServerTests/Android.bp
+++ b/services/tests/InputMethodSystemServerTests/Android.bp
@@ -138,3 +138,17 @@ android_test {
enabled: false,
},
}
+
+test_module_config {
+ name: "FrameworksInputMethodSystemServerTests_server_inputmethod",
+ base: "FrameworksInputMethodSystemServerTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.inputmethod"],
+}
+
+test_module_config {
+ name: "FrameworksImeTests_android_inputmethodservice",
+ base: "FrameworksImeTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.inputmethodservice"],
+}
diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp
index 6fd21f74cf8c..75db31679a88 100644
--- a/services/tests/PackageManagerServiceTests/host/Android.bp
+++ b/services/tests/PackageManagerServiceTests/host/Android.bp
@@ -88,3 +88,10 @@ genrule {
" && $(location soong_zip) -o $(genDir)/temp.apk -L 0 -C $(genDir)/apk -D $(genDir)/apk" +
" && $(location zipalign) -f 4 $(genDir)/temp.apk $(out)",
}
+
+test_module_config_host {
+ name: "PackageManagerServiceHostTests_test_overlayactorvisibilitytest",
+ base: "PackageManagerServiceHostTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.pm.test.OverlayActorVisibilityTest"],
+}
diff --git a/services/tests/PackageManagerServiceTests/server/Android.bp b/services/tests/PackageManagerServiceTests/server/Android.bp
index 598e27372075..e26213eadde3 100644
--- a/services/tests/PackageManagerServiceTests/server/Android.bp
+++ b/services/tests/PackageManagerServiceTests/server/Android.bp
@@ -164,3 +164,25 @@ java_genrule {
"done && " +
"$(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res",
}
+
+test_module_config {
+ name: "PackageManagerServiceServerTests_server_pm_Presubmit",
+ base: "PackageManagerServiceServerTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.pm."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
+
+test_module_config {
+ name: "PackageManagerServiceServerTests_server_pm_Postsubmit",
+ base: "PackageManagerServiceServerTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.pm."],
+ include_annotations: ["android.platform.test.annotations.Postsubmit"],
+}
diff --git a/services/tests/PackageManagerServiceTests/unit/Android.bp b/services/tests/PackageManagerServiceTests/unit/Android.bp
index c93f48225e48..db88b166b13a 100644
--- a/services/tests/PackageManagerServiceTests/unit/Android.bp
+++ b/services/tests/PackageManagerServiceTests/unit/Android.bp
@@ -47,3 +47,10 @@ android_test {
platform_apis: true,
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "PackageManagerServiceUnitTests_verify_domain",
+ base: "PackageManagerServiceUnitTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.pm.test.verify.domain"],
+}
diff --git a/services/tests/displayservicetests/Android.bp b/services/tests/displayservicetests/Android.bp
index 3bafe7296fff..61350bf24868 100644
--- a/services/tests/displayservicetests/Android.bp
+++ b/services/tests/displayservicetests/Android.bp
@@ -56,3 +56,13 @@ android_test {
enabled: false,
},
}
+
+test_module_config {
+ name: "DisplayServiceTests_server_display",
+ base: "DisplayServiceTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.display"],
+}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
index 026fcc486a92..5bb8ded6920e 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayManagerServiceTest.java
@@ -64,6 +64,7 @@ import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManagerInternal;
import android.app.ActivityOptions.LaunchCookie;
import android.app.PropertyInvalidatedCache;
import android.companion.virtual.IVirtualDevice;
@@ -358,6 +359,7 @@ public class DisplayManagerServiceTest {
@Mock DisplayDeviceConfig mMockDisplayDeviceConfig;
@Mock PackageManagerInternal mMockPackageManagerInternal;
@Mock DisplayManagerInternal mMockDisplayManagerInternal;
+ @Mock ActivityManagerInternal mMockActivityManagerInternal;
@Mock DisplayAdapter mMockDisplayAdapter;
@Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor;
@@ -388,6 +390,8 @@ public class DisplayManagerServiceTest {
PackageManagerInternal.class, mMockPackageManagerInternal);
mLocalServiceKeeperRule.overrideLocalService(
DisplayManagerInternal.class, mMockDisplayManagerInternal);
+ mLocalServiceKeeperRule.overrideLocalService(
+ ActivityManagerInternal.class, mMockActivityManagerInternal);
Display display = mock(Display.class);
when(display.getDisplayAdjustments()).thenReturn(new DisplayAdjustments());
when(display.getBrightnessInfo()).thenReturn(mock(BrightnessInfo.class));
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java
index 30c384a03883..5e868a3089f6 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayOffloadSessionImplTest.java
@@ -38,7 +38,7 @@ public class DisplayOffloadSessionImplTest {
private DisplayManagerInternal.DisplayOffloader mDisplayOffloader;
@Mock
- private DisplayPowerControllerInterface mDisplayPowerController;
+ private DisplayPowerController mDisplayPowerController;
private DisplayOffloadSessionImpl mSession;
diff --git a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
index a7e0ebdd6de1..120cc84193cd 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -118,7 +118,7 @@ public class LocalDisplayAdapterTest {
@Mock
private DisplayManagerFlags mFlags;
@Mock
- private DisplayPowerControllerInterface mMockedDisplayPowerController;
+ private DisplayPowerController mMockedDisplayPowerController;
private Handler mHandler;
diff --git a/services/tests/dreamservicetests/Android.bp b/services/tests/dreamservicetests/Android.bp
index 6369d4564bf2..1f0e975a4c90 100644
--- a/services/tests/dreamservicetests/Android.bp
+++ b/services/tests/dreamservicetests/Android.bp
@@ -42,3 +42,13 @@ android_test {
enabled: false,
},
}
+
+test_module_config {
+ name: "DreamServiceTests_server_dreams",
+ base: "DreamServiceTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.dreams"],
+}
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 9808d54202e5..5a7693194d88 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -333,3 +333,73 @@ test_module_config {
test_suites: ["device-tests"],
include_filters: ["com.android.server.utils"],
}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_android_server",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_job",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.job"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_tare",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.tare"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_backup",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.backup"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_rescuepartytest",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.RescuePartyTest"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_power",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power"],
+}
+
+test_module_config {
+ name: "FrameworksMockingServicesTests_server_trust",
+ base: "FrameworksMockingServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.trust"],
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 51aa5284f5f2..3b284a290d63 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -90,7 +90,6 @@ import static org.mockito.Mockito.verify;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.ApplicationExitInfo;
-import android.app.IApplicationThread;
import android.app.IServiceConnection;
import android.content.ComponentName;
import android.content.Context;
@@ -164,6 +163,10 @@ public class MockingOomAdjusterTests {
private static int sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ
+ ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
+ private static int sFirstUiCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 10;
+ private static int sFirstNonUiCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 20;
+ private static int sUiTierSize = 5;
+
private Context mContext;
private PackageManagerInternal mPackageManagerInternal;
private ActivityManagerService mService;
@@ -232,9 +235,6 @@ public class MockingOomAdjusterTests {
mInjector);
mService.mOomAdjuster.mAdjSeq = 10000;
mService.mWakefulness = new AtomicInteger(PowerManagerInternal.WAKEFULNESS_AWAKE);
- if (mService.mConstants.USE_TIERED_CACHED_ADJ) {
- sFirstCachedAdj = ProcessList.CACHED_APP_MIN_ADJ + 10;
- }
mSetFlagsRule.enableFlags(Flags.FLAG_NEW_FGS_RESTRICTION_LOGIC);
}
@@ -473,7 +473,8 @@ public class MockingOomAdjusterTests {
mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj(app);
- final int expectedAdj = sFirstCachedAdj;
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstUiCachedAdj : sFirstCachedAdj;
assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj,
SCHED_GROUP_BACKGROUND);
}
@@ -701,7 +702,9 @@ public class MockingOomAdjusterTests {
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertEquals(sFirstCachedAdj, app.mState.getSetAdj());
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstUiCachedAdj : sFirstCachedAdj;
+ assertEquals(expectedAdj, app.mState.getSetAdj());
// Follow up should not have been called again.
verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
followUpTimeCaptor.capture());
@@ -836,7 +839,9 @@ public class MockingOomAdjusterTests {
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, CACHED_APP_MIN_ADJ,
+ int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstUiCachedAdj : CACHED_APP_MIN_ADJ;
+ assertProcStates(app, PROCESS_STATE_LAST_ACTIVITY, expectedAdj,
SCHED_GROUP_BACKGROUND, "previous-expired");
// Follow up should not have been called again.
verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
@@ -877,9 +882,15 @@ public class MockingOomAdjusterTests {
for (int i = 0; i < numberOfApps; i++) {
final int mruIndex = numberOfApps - i - 1;
- int expectedAdj = CACHED_APP_MIN_ADJ + (mruIndex * 2 * CACHED_APP_IMPORTANCE_LEVELS);
- if (expectedAdj > CACHED_APP_MAX_ADJ) {
- expectedAdj = CACHED_APP_MAX_ADJ;
+ int expectedAdj;
+ if (mService.mConstants.USE_TIERED_CACHED_ADJ) {
+ expectedAdj = (i < numberOfApps - sUiTierSize)
+ ? sFirstNonUiCachedAdj : sFirstUiCachedAdj + mruIndex;
+ } else {
+ expectedAdj = CACHED_APP_MIN_ADJ + (mruIndex * 2 * CACHED_APP_IMPORTANCE_LEVELS);
+ if (expectedAdj > CACHED_APP_MAX_ADJ) {
+ expectedAdj = CACHED_APP_MAX_ADJ;
+ }
}
assertProcStates(apps[i], PROCESS_STATE_LAST_ACTIVITY, expectedAdj,
SCHED_GROUP_BACKGROUND, "previous-expired");
@@ -1003,7 +1014,9 @@ public class MockingOomAdjusterTests {
updateOomAdj(client, app);
doReturn(null).when(mService).getTopApp();
- assertProcStates(app, PROCESS_STATE_SERVICE, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_SERVICE, expectedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -1053,7 +1066,9 @@ public class MockingOomAdjusterTests {
mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj(app);
- assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -1469,7 +1484,9 @@ public class MockingOomAdjusterTests {
bindProvider(app, app, null, null, false);
updateOomAdj(app);
- assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -1484,7 +1501,9 @@ public class MockingOomAdjusterTests {
mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj(app, client);
- assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND);
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND);
}
@SuppressWarnings("GuardedBy")
@@ -1592,7 +1611,9 @@ public class MockingOomAdjusterTests {
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND,
"cch-empty");
// Follow up should not have been called again.
verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
@@ -2623,12 +2644,11 @@ public class MockingOomAdjusterTests {
MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
final int userOwner = 0;
final int userOther = 1;
- final int cachedAdj1 = mService.mConstants.USE_TIERED_CACHED_ADJ
- ? CACHED_APP_MIN_ADJ + 10
- : CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
- final int cachedAdj2 = mService.mConstants.USE_TIERED_CACHED_ADJ
- ? CACHED_APP_MIN_ADJ + 10
- : cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
+
+ // cachedAdj1 and cachedAdj2 will be read if USE_TIERED_CACHED_ADJ is disabled. Otherwise,
+ // sFirstUiCachedAdj and sFirstNonUiCachedAdj are used instead.
+ final int cachedAdj1 = CACHED_APP_MIN_ADJ + ProcessList.CACHED_APP_IMPORTANCE_LEVELS;
+ final int cachedAdj2 = cachedAdj1 + ProcessList.CACHED_APP_IMPORTANCE_LEVELS * 2;
doReturn(userOwner).when(mService.mUserController).getCurrentUserId();
final ArrayList<ProcessRecord> lru = mService.mProcessList.getLruProcessesLOSP();
@@ -2669,8 +2689,12 @@ public class MockingOomAdjusterTests {
mService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
updateOomAdj();
- assertProcStates(app, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-ui-services");
- assertProcStates(app2, true, PROCESS_STATE_SERVICE, cachedAdj2, "cch-started-services");
+ assertProcStates(app, true, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstUiCachedAdj : cachedAdj1,
+ "cch-started-ui-services");
+ assertProcStates(app2, true, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj2,
+ "cch-started-services");
app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
app.mState.setAdjType(null);
@@ -2686,7 +2710,10 @@ public class MockingOomAdjusterTests {
s.lastActivity = now - mService.mConstants.MAX_SERVICE_INACTIVITY - 1;
updateOomAdj();
- assertProcStates(app, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
+ // hasShownUi was set to false for 'app', so 920 is expected for USE_TIERED_CACHED_ADJ.
+ assertProcStates(app, true, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+ "cch-started-services");
app.mServices.stopService(s);
app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
@@ -2705,7 +2732,9 @@ public class MockingOomAdjusterTests {
updateOomAdj();
assertProcStates(app, false, PROCESS_STATE_SERVICE, SERVICE_ADJ, "started-services");
- assertProcStates(app2, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
+ assertProcStates(app2, true, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+ "cch-started-services");
app.mState.setSetProcState(PROCESS_STATE_NONEXISTENT);
app.mState.setAdjType(null);
@@ -2715,13 +2744,17 @@ public class MockingOomAdjusterTests {
updateOomAdj();
assertProcStates(app, false, PROCESS_STATE_SERVICE, SERVICE_ADJ, "started-services");
- assertProcStates(app2, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
+ assertProcStates(app2, true, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+ "cch-started-services");
doReturn(userOther).when(mService.mUserController).getCurrentUserId();
mService.mOomAdjuster.handleUserSwitchedLocked();
updateOomAdj();
- assertProcStates(app, true, PROCESS_STATE_SERVICE, cachedAdj1, "cch-started-services");
+ assertProcStates(app, true, PROCESS_STATE_SERVICE,
+ mService.mConstants.USE_TIERED_CACHED_ADJ ? sFirstNonUiCachedAdj : cachedAdj1,
+ "cch-started-services");
assertProcStates(app2, false, PROCESS_STATE_SERVICE, SERVICE_ADJ, "started-services");
}
@@ -2998,7 +3031,9 @@ public class MockingOomAdjusterTests {
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertProcStates(app, PROCESS_STATE_SERVICE, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app, PROCESS_STATE_SERVICE, expectedAdj, SCHED_GROUP_BACKGROUND,
"cch-started-services");
// Follow up should not have been called again.
verify(mService.mHandler).sendEmptyMessageAtTime(eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG),
@@ -3031,14 +3066,16 @@ public class MockingOomAdjusterTests {
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertProcStates(app1, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+ final int expectedAdj = mService.mConstants.USE_TIERED_CACHED_ADJ
+ ? sFirstNonUiCachedAdj : sFirstCachedAdj;
+ assertProcStates(app1, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND,
"cch-empty");
verify(mService.mHandler, atLeastOnce()).sendEmptyMessageAtTime(
eq(FOLLOW_UP_OOMADJUSTER_UPDATE_MSG), followUpTimeCaptor.capture());
mInjector.jumpUptimeAheadTo(followUpTimeCaptor.getValue());
mService.mOomAdjuster.updateOomAdjFollowUpTargetsLocked();
- assertProcStates(app2, PROCESS_STATE_CACHED_EMPTY, sFirstCachedAdj, SCHED_GROUP_BACKGROUND,
+ assertProcStates(app2, PROCESS_STATE_CACHED_EMPTY, expectedAdj, SCHED_GROUP_BACKGROUND,
"cch-empty");
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp b/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp
index e94b8ad0a9ac..6a16d1e14795 100644
--- a/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp
+++ b/services/tests/mockingservicestests/src/com/android/server/rollback/Android.bp
@@ -54,3 +54,13 @@ android_test {
"automotive-tests",
],
}
+
+test_module_config {
+ name: "RollbackPackageHealthObserverTests_server_rollback",
+ base: "RollbackPackageHealthObserverTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.rollback"],
+}
diff --git a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
index 7d0447097375..b2ca991a4aa8 100644
--- a/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
+++ b/services/tests/performancehinttests/src/com/android/server/power/hint/HintManagerServiceTest.java
@@ -631,7 +631,7 @@ public class HintManagerServiceTest {
CountDownLatch stopLatch2 = new CountDownLatch(1);
// negative value used for test only to avoid conflicting with any real thread that exists
int isoProc1 = -100;
- int isoProc2 = 9999;
+ int isoProc2 = 99999999;
when(mAmInternalMock.getIsolatedProcesses(eq(UID))).thenReturn(List.of(0));
int[] tids2 = createThreads(threadCount, stopLatch2);
int[] tids2WithIsolated = Arrays.copyOf(tids2, tids2.length + 2);
@@ -658,7 +658,7 @@ public class HintManagerServiceTest {
verify(mNativeWrapperMock, never()).halSetThreads(eq(sessionPtr1), any());
verify(mNativeWrapperMock, never()).halSetThreads(eq(sessionPtr2), any());
// the new TIDs pending list should be updated
- assertArrayEquals(session2.getTidsInternal(), expectedTids2);
+ assertArrayEquals(expectedTids2, session2.getTidsInternal());
reset(mNativeWrapperMock);
// this should resume and update the threads so those never-existed invalid isolated
@@ -713,8 +713,8 @@ public class HintManagerServiceTest {
// in background, set threads for session 1 then it should not be force paused next time
session1.setThreads(SESSION_TIDS_A);
// the new TIDs pending list should be updated
- assertArrayEquals(session1.getTidsInternal(), SESSION_TIDS_A);
- assertArrayEquals(session2.getTidsInternal(), expectedTids2);
+ assertArrayEquals(SESSION_TIDS_A, session1.getTidsInternal());
+ assertArrayEquals(expectedTids2, session2.getTidsInternal());
verifyAllHintsEnabled(session1, false);
verifyAllHintsEnabled(session2, false);
reset(mNativeWrapperMock);
diff --git a/services/tests/powerservicetests/Android.bp b/services/tests/powerservicetests/Android.bp
index 729dcbd11f42..f8cc6d0fedb6 100644
--- a/services/tests/powerservicetests/Android.bp
+++ b/services/tests/powerservicetests/Android.bp
@@ -44,3 +44,13 @@ android_test {
enabled: false,
},
}
+
+test_module_config {
+ name: "PowerServiceTests_server_power",
+ base: "PowerServiceTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power"],
+}
diff --git a/services/tests/powerstatstests/Android.bp b/services/tests/powerstatstests/Android.bp
index 91c62be3d88a..0e922ceee26e 100644
--- a/services/tests/powerstatstests/Android.bp
+++ b/services/tests/powerstatstests/Android.bp
@@ -79,3 +79,23 @@ android_ravenwood_test {
],
auto_gen_config: true,
}
+
+test_module_config {
+ name: "PowerStatsTests_stats_bstatscputimesvalidationtest",
+ base: "PowerStatsTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power.stats.BstatsCpuTimesValidationTest"],
+}
+
+test_module_config {
+ name: "PowerStatsTests_power_stats",
+ base: "PowerStatsTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power.stats"],
+}
diff --git a/services/tests/powerstatstests/TEST_MAPPING b/services/tests/powerstatstests/TEST_MAPPING
index fb243616292d..1e8d2de36023 100644
--- a/services/tests/powerstatstests/TEST_MAPPING
+++ b/services/tests/powerstatstests/TEST_MAPPING
@@ -14,8 +14,7 @@
"name": "PowerStatsTestsRavenwood",
"host": true,
"options": [
- {"include-filter": "com.android.server.power.stats"},
- {"exclude-annotation": "android.platform.test.annotations.DisabledOnRavenwood"}
+ {"include-filter": "com.android.server.power.stats"}
]
}
],
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index 09f81f736b36..a862c43fd841 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -678,3 +678,176 @@ test_module_config {
test_suites: ["device-tests"],
include_filters: ["com.android.server.input"],
}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_job",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.job"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_tare",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.tare"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_usage",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.usage"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_om",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.om"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_accessibility",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.accessibility"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_binarytransparencyservicetest",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.BinaryTransparencyServiceTest"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_pinnerservicetest",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.PinnerServiceTest"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_am",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.am."],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_hdmi",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.hdmi"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_logcat",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.logcat"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_net_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.net."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_policy_Presubmit",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.policy."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_policy",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.policy."],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_power",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_power_hint",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.power.hint"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_location_contexthub_Postsubmit",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.location.contexthub."],
+ include_annotations: ["android.platform.test.annotations.Postsubmit"],
+}
+
+test_module_config {
+ name: "FrameworksServicesTests_server_input",
+ base: "FrameworksServicesTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.input"],
+}
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt b/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt
index 8753b251ac98..019ccf93fa11 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt
+++ b/services/tests/servicestests/src/com/android/server/accessibility/MouseKeysInterceptorTest.kt
@@ -48,6 +48,7 @@ import org.mockito.MockitoAnnotations
import java.util.LinkedList
import java.util.Queue
import android.util.ArraySet
+import android.view.InputDevice
/**
* Tests for {@link MouseKeysInterceptor}
@@ -68,6 +69,8 @@ class MouseKeysInterceptorTest {
}
private lateinit var mouseKeysInterceptor: MouseKeysInterceptor
+ private lateinit var inputDevice: InputDevice
+
private val clock = OffsettableClock()
private val testLooper = TestLooper { clock.now() }
private val nextInterceptor = TrackingInterceptor()
@@ -98,6 +101,10 @@ class MouseKeysInterceptorTest {
testSession = InputManagerGlobal.createTestSession(iInputManager)
mockInputManager = InputManager(context)
+ inputDevice = createInputDevice(DEVICE_ID)
+ Mockito.`when`(iInputManager.getInputDevice(DEVICE_ID))
+ .thenReturn(inputDevice)
+
Mockito.`when`(mockVirtualDeviceManagerInternal.getDeviceIdsForUid(Mockito.anyInt()))
.thenReturn(ArraySet(setOf(DEVICE_ID)))
LocalServices.removeServiceForTest(VirtualDeviceManagerInternal::class.java)
@@ -115,7 +122,8 @@ class MouseKeysInterceptorTest {
Mockito.`when`(iInputManager.inputDeviceIds).thenReturn(intArrayOf(DEVICE_ID))
Mockito.`when`(mockAms.traceManager).thenReturn(mockTraceManager)
- mouseKeysInterceptor = MouseKeysInterceptor(mockAms, testLooper.looper, DISPLAY_ID)
+ mouseKeysInterceptor = MouseKeysInterceptor(mockAms, mockInputManager,
+ testLooper.looper, DISPLAY_ID)
mouseKeysInterceptor.next = nextInterceptor
}
@@ -281,6 +289,17 @@ class MouseKeysInterceptorTest {
}
}
+ private fun createInputDevice(
+ deviceId: Int,
+ generation: Int = -1
+ ): InputDevice =
+ InputDevice.Builder()
+ .setId(deviceId)
+ .setName("Device $deviceId")
+ .setDescriptor("descriptor $deviceId")
+ .setGeneration(generation)
+ .build()
+
private class TrackingInterceptor : BaseEventStreamTransformation() {
val events: Queue<KeyEvent> = LinkedList()
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 2a55521ab329..a25621a8975f 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -90,6 +90,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IRemoteCallback;
+import android.os.IpcDataCache;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManagerInternal;
@@ -197,6 +198,9 @@ public class UserControllerTest {
@Before
public void setUp() throws Exception {
runWithDexmakerShareClassLoader(() -> {
+ // Disable binder caches in this process.
+ IpcDataCache.disableForTestMode();
+
mInjector = spy(new TestInjector(getInstrumentation().getTargetContext()));
doNothing().when(mInjector).clearAllLockedTasks(anyString());
doNothing().when(mInjector).startHomeActivity(anyInt(), anyString());
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
index 4c3a233fdd97..760d38e855a6 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/PreAuthInfoTest.java
@@ -264,6 +264,22 @@ public class PreAuthInfoTest {
assertThat(preAuthInfo.eligibleSensors).hasSize(0);
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
+ public void testMandatoryBiometricsNegativeButtonText_whenSet()
+ throws Exception {
+ when(mTrustManager.isInSignificantPlace()).thenReturn(false);
+
+ final BiometricSensor sensor = getFaceSensor();
+ final PromptInfo promptInfo = new PromptInfo();
+ promptInfo.setAuthenticators(BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
+ promptInfo.setNegativeButtonText(TEST_PACKAGE_NAME);
+ final PreAuthInfo preAuthInfo = PreAuthInfo.create(mTrustManager, mDevicePolicyManager,
+ mSettingObserver, List.of(sensor), 0 /* userId */, promptInfo, TEST_PACKAGE_NAME,
+ false /* checkDevicePolicyManager */, mContext, mBiometricCameraManager);
+ assertThat(promptInfo.getNegativeButtonText()).isEqualTo(TEST_PACKAGE_NAME);
+ }
+
private BiometricSensor getFingerprintSensor() {
BiometricSensor sensor = new BiometricSensor(mContext, SENSOR_ID_FINGERPRINT,
TYPE_FINGERPRINT, BiometricManager.Authenticators.BIOMETRIC_STRONG,
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 791215695f57..e652df5cdf1a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -34,6 +34,7 @@ import android.content.pm.UserProperties;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.os.IpcDataCache;
import android.os.PersistableBundle;
import android.os.UserHandle;
import android.os.UserManager;
@@ -100,6 +101,9 @@ public final class UserManagerTest {
@Before
public void setUp() throws Exception {
+ // Disable binder caches in this process.
+ IpcDataCache.disableForTestMode();
+
mOriginalCurrentUserId = ActivityManager.getCurrentUser();
mUserManager = UserManager.get(mContext);
mActivityManager = mContext.getSystemService(ActivityManager.class);
diff --git a/services/tests/timetests/Android.bp b/services/tests/timetests/Android.bp
index 23ab85996fff..05a1433c128e 100644
--- a/services/tests/timetests/Android.bp
+++ b/services/tests/timetests/Android.bp
@@ -25,3 +25,27 @@ android_test {
certificate: "platform",
test_suites: ["device-tests"],
}
+
+test_module_config {
+ name: "FrameworksTimeServicesTests_time",
+ base: "FrameworksTimeServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: [
+ "com.android.server.timezonedetector.",
+ "com.android.server.timedetector.",
+ ],
+}
+
+test_module_config {
+ name: "FrameworksTimeServicesTests_server_timedetector",
+ base: "FrameworksTimeServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.timedetector."],
+}
+
+test_module_config {
+ name: "FrameworksTimeServicesTests_server_timezonedetector",
+ base: "FrameworksTimeServicesTests",
+ test_suites: ["device-tests"],
+ include_filters: ["com.android.server.timezonedetector."],
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
index b3ec2153542a..c9d5241c57b7 100644
--- a/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
+++ b/services/tests/uiservicestests/src/com/android/server/UiServiceTestCase.java
@@ -30,6 +30,7 @@ import android.testing.TestableContext;
import androidx.test.InstrumentationRegistry;
+import com.android.server.pm.UserManagerInternal;
import com.android.server.uri.UriGrantsManagerInternal;
import org.junit.After;
@@ -41,6 +42,7 @@ import org.mockito.MockitoAnnotations;
public class UiServiceTestCase {
@Mock protected PackageManagerInternal mPmi;
+ @Mock protected UserManagerInternal mUmi;
@Mock protected UriGrantsManagerInternal mUgmInternal;
protected static final String PKG_N_MR1 = "com.example.n_mr1";
@@ -92,6 +94,8 @@ public class UiServiceTestCase {
}
});
+ LocalServices.removeServiceForTest(UserManagerInternal.class);
+ LocalServices.addService(UserManagerInternal.class, mUmi);
LocalServices.removeServiceForTest(UriGrantsManagerInternal.class);
LocalServices.addService(UriGrantsManagerInternal.class, mUgmInternal);
when(mUgmInternal.checkGrantUriPermission(
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
index 7933f7ab06cd..4a199738cccd 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/DefaultDeviceEffectsApplierTest.java
@@ -46,6 +46,7 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.display.ColorDisplayManager;
import android.os.PowerManager;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.service.notification.ZenDeviceEffects;
import android.testing.TestableContext;
@@ -64,6 +65,9 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
@RunWith(TestParameterInjector.class)
public class DefaultDeviceEffectsApplierTest {
@@ -89,6 +93,8 @@ public class DefaultDeviceEffectsApplierTest {
mApplier = new DefaultDeviceEffectsApplier(mContext);
verify(mWallpaperManager).isWallpaperSupported();
+
+ ZenLog.clear();
}
@Test
@@ -110,6 +116,41 @@ public class DefaultDeviceEffectsApplierTest {
}
@Test
+ @EnableFlags(android.app.Flags.FLAG_MODES_API)
+ public void apply_logsToZenLog() {
+ when(mPowerManager.isInteractive()).thenReturn(true);
+ ArgumentCaptor<BroadcastReceiver> broadcastReceiverCaptor =
+ ArgumentCaptor.forClass(BroadcastReceiver.class);
+ ArgumentCaptor<IntentFilter> intentFilterCaptor =
+ ArgumentCaptor.forClass(IntentFilter.class);
+
+ ZenDeviceEffects effects = new ZenDeviceEffects.Builder()
+ .setShouldDisplayGrayscale(true)
+ .setShouldUseNightMode(true)
+ .build();
+ mApplier.apply(effects, ORIGIN_APP);
+
+ String zenLog = getZenLog();
+ assertThat(zenLog).contains("apply_device_effect: displayGrayscale -> true");
+ assertThat(zenLog).contains("schedule_device_effect: nightMode -> true");
+ assertThat(zenLog).doesNotContain("apply_device_effect: nightMode");
+
+ verify(mContext).registerReceiver(broadcastReceiverCaptor.capture(),
+ intentFilterCaptor.capture(), anyInt());
+ BroadcastReceiver screenOffReceiver = broadcastReceiverCaptor.getValue();
+ screenOffReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
+
+ zenLog = getZenLog();
+ assertThat(zenLog).contains("apply_device_effect: nightMode -> true");
+ }
+
+ private static String getZenLog() {
+ StringWriter zenLogWriter = new StringWriter();
+ ZenLog.dump(new PrintWriter(zenLogWriter), "");
+ return zenLogWriter.toString();
+ }
+
+ @Test
public void apply_removesEffects() {
mSetFlagsRule.enableFlags(android.app.Flags.FLAG_MODES_API);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index fb82b872cf80..4e376aa627e5 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -1542,6 +1542,7 @@ public class ManagedServicesTest extends UiServiceTestCase {
assertTrue(componentsToUnbind.get(0).contains(ComponentName.unflattenFromString("c/c")));
}
+ @SuppressWarnings("GuardedBy")
@Test
public void populateComponentsToBind() {
ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
@@ -1565,7 +1566,8 @@ public class ManagedServicesTest extends UiServiceTestCase {
SparseArray<Set<ComponentName>> componentsToBind = new SparseArray<>();
- service.populateComponentsToBind(componentsToBind, users, approvedComponentsByUser);
+ service.populateComponentsToBind(componentsToBind, users, approvedComponentsByUser,
+ /* isVisibleBackgroundUser= */ false);
assertEquals(2, componentsToBind.size());
assertEquals(1, componentsToBind.get(0).size());
@@ -1575,6 +1577,33 @@ public class ManagedServicesTest extends UiServiceTestCase {
assertTrue(componentsToBind.get(10).contains(ComponentName.unflattenFromString("c/c")));
}
+ @SuppressWarnings("GuardedBy")
+ @Test
+ public void populateComponentsToBind_isVisibleBackgroundUser_addComponentsToBindButNotAddToEnabledComponent() {
+ ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles, mIpm,
+ APPROVAL_BY_COMPONENT);
+
+ SparseArray<ArraySet<ComponentName>> approvedComponentsByUser = new SparseArray<>();
+ ArraySet<ComponentName> allowed = new ArraySet<>();
+ allowed.add(ComponentName.unflattenFromString("pkg1/cmp1"));
+ approvedComponentsByUser.put(11, allowed);
+ IntArray users = new IntArray();
+ users.add(11);
+
+ SparseArray<Set<ComponentName>> componentsToBind = new SparseArray<>();
+
+ service.populateComponentsToBind(componentsToBind, users, approvedComponentsByUser,
+ /* isVisibleBackgroundUser= */ true);
+
+ assertEquals(1, componentsToBind.size());
+ assertEquals(1, componentsToBind.get(11).size());
+ assertTrue(componentsToBind.get(11).contains(ComponentName.unflattenFromString(
+ "pkg1/cmp1")));
+ assertThat(service.isComponentEnabledForCurrentProfiles(
+ new ComponentName("pkg1", "cmp1"))).isFalse();
+ assertThat(service.isComponentEnabledForPackage("pkg1")).isFalse();
+ }
+
@Test
public void testOnNullBinding() throws Exception {
Context context = mock(Context.class);
diff --git a/services/tests/wmtests/Android.bp b/services/tests/wmtests/Android.bp
index 604869c7f0ca..289f8a90e0bd 100644
--- a/services/tests/wmtests/Android.bp
+++ b/services/tests/wmtests/Android.bp
@@ -109,3 +109,35 @@ android_test {
":OverlayTestApp",
],
}
+
+test_module_config {
+ name: "WmTests_server_policy_Presubmit",
+ base: "WmTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.policy."],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
+
+test_module_config {
+ name: "WmTests_server_policy",
+ base: "WmTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.policy."],
+}
+
+test_module_config {
+ name: "WmTests_wm_utils_Presubmit",
+ base: "WmTests",
+ test_suites: [
+ "automotive-tests",
+ "device-tests",
+ ],
+ include_filters: ["com.android.server.wm.utils"],
+ include_annotations: ["android.platform.test.annotations.Presubmit"],
+}
diff --git a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
index 07934ea90b7e..e694c0b4afc1 100644
--- a/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/PhoneWindowManagerTests.java
@@ -188,7 +188,7 @@ public class PhoneWindowManagerTests {
.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED);
int[] outAppOp = new int[1];
assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_WALLPAPER,
- /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp));
+ /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY));
assertThat(outAppOp[0]).isEqualTo(AppOpsManager.OP_NONE);
}
@@ -198,7 +198,7 @@ public class PhoneWindowManagerTests {
.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED);
int[] outAppOp = new int[1];
assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_ACCESSIBILITY_OVERLAY,
- /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp));
+ /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY));
assertThat(outAppOp[0]).isEqualTo(AppOpsManager.OP_CREATE_ACCESSIBILITY_OVERLAY);
}
@@ -208,7 +208,7 @@ public class PhoneWindowManagerTests {
.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED);
int[] outAppOp = new int[1];
assertEquals(ADD_OKAY, mPhoneWindowManager.checkAddPermission(TYPE_ACCESSIBILITY_OVERLAY,
- /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp));
+ /* isRoundedCornerOverlay= */ false, "test.pkg", outAppOp, DEFAULT_DISPLAY));
assertThat(outAppOp[0]).isEqualTo(AppOpsManager.OP_NONE);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 4f94704ee39f..c706d5200443 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -1047,6 +1047,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
info.packageName = packageName;
WindowProcessController wpc = new WindowProcessController(
mAtm, info, packageName, 0, userId, null, mMockListener);
+ mAtm.mInternal.preBindApplication(wpc, info);
wpc.setThread(mock(IApplicationThread.class));
return wpc;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
index 44837d7ba32e..20dcdde63cc4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/BackNavigationControllerTests.java
@@ -110,6 +110,7 @@ public class BackNavigationControllerTests extends WindowTestsBase {
mWindowManagerInternal = mock(WindowManagerInternal.class);
LocalServices.addService(WindowManagerInternal.class, mWindowManagerInternal);
mBackAnimationAdapter = mock(BackAnimationAdapter.class);
+ doReturn(true).when(mBackAnimationAdapter).isAnimatable(anyInt());
mNavigationMonitor = mock(BackNavigationController.NavigationMonitor.class);
mRootHomeTask = initHomeActivity();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index 57839e2b795e..ffe38936bcc1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -244,6 +244,19 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
mWm.clearForcedDisplaySize(mSecondaryDisplay.getDisplayId());
assertEquals(mSecondaryDisplay.mInitialDisplayWidth, mSecondaryDisplay.mBaseDisplayWidth);
assertEquals(mSecondaryDisplay.mInitialDisplayHeight, mSecondaryDisplay.mBaseDisplayHeight);
+
+ // Forced size can be cleared even if the initial display size is smaller than max width.
+ final int maxWidth = mSecondaryDisplay.mInitialDisplayWidth - 20;
+ mSecondaryDisplay.setMaxUiWidth(maxWidth);
+ assertEquals(maxWidth, mSecondaryDisplay.mBaseDisplayWidth);
+ mSecondaryDisplay.setForcedSize(maxWidth - 10, maxWidth + 10);
+ assertNotEquals(maxWidth, mSecondaryDisplay.mBaseDisplayHeight);
+ assertTrue(mSecondaryDisplay.mIsSizeForced);
+
+ mWm.clearForcedDisplaySize(mSecondaryDisplay.mDisplayId);
+ assertFalse(mSecondaryDisplay.mIsSizeForced);
+ assertEquals(maxWidth, mSecondaryDisplay.mBaseDisplayWidth);
+ assertEquals(0, mSettingsProvider.getSettings(originalInfo).mForcedWidth);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index d62c626f9a90..eebb487d16cd 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -60,7 +60,7 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
@Override
public int checkAddPermission(int type, boolean isRoundedCornerOverlay, String packageName,
- int[] outAppOp) {
+ int[] outAppOp, int displayId) {
return 0;
}
diff --git a/telephony/common/android/telephony/LocationAccessPolicy.java b/telephony/common/android/telephony/LocationAccessPolicy.java
index feea55bff125..a6781478a765 100644
--- a/telephony/common/android/telephony/LocationAccessPolicy.java
+++ b/telephony/common/android/telephony/LocationAccessPolicy.java
@@ -33,7 +33,6 @@ import android.util.Log;
import android.widget.Toast;
import com.android.internal.telephony.TelephonyPermissions;
-import com.android.internal.telephony.flags.Flags;
import com.android.internal.telephony.util.TelephonyUtils;
/**
@@ -312,18 +311,10 @@ public final class LocationAccessPolicy {
// This avoid breaking legacy code that rely on public-facing APIs to access cell location,
// and it doesn't create an info leak risk because the cell location is stored in the phone
// process anyway, and the system server already has location access.
- if (Flags.supportPhoneUidCheckForMultiuser()) {
- if (TelephonyPermissions.isSystemOrPhone(query.callingUid)
- || UserHandle.isSameApp(query.callingUid, Process.NETWORK_STACK_UID)
- || UserHandle.isSameApp(query.callingUid, Process.ROOT_UID)) {
- return LocationPermissionResult.ALLOWED;
- }
- } else {
- if (query.callingUid == Process.PHONE_UID || query.callingUid == Process.SYSTEM_UID
- || query.callingUid == Process.NETWORK_STACK_UID
- || query.callingUid == Process.ROOT_UID) {
- return LocationPermissionResult.ALLOWED;
- }
+ if (TelephonyPermissions.isSystemOrPhone(query.callingUid)
+ || UserHandle.isSameApp(query.callingUid, Process.NETWORK_STACK_UID)
+ || UserHandle.isSameApp(query.callingUid, Process.ROOT_UID)) {
+ return LocationPermissionResult.ALLOWED;
}
// Check the system-wide requirements. If the location main switch is off and the caller is
diff --git a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
index 7ed26fb549f9..b80610a76cc8 100644
--- a/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/common/com/android/internal/telephony/TelephonyPermissions.java
@@ -35,7 +35,6 @@ import android.telephony.TelephonyManager;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.flags.Flags;
import java.util.HashMap;
import java.util.HashSet;
@@ -934,12 +933,8 @@ public final class TelephonyPermissions {
* as system user or not.
*/
public static boolean isSystemOrPhone(int uid) {
- if (Flags.supportPhoneUidCheckForMultiuser()) {
- return UserHandle.isSameApp(uid, Process.SYSTEM_UID) || UserHandle.isSameApp(uid,
- Process.PHONE_UID);
- } else {
- return uid == Process.SYSTEM_UID || uid == Process.PHONE_UID;
- }
+ return UserHandle.isSameApp(uid, Process.SYSTEM_UID) || UserHandle.isSameApp(uid,
+ Process.PHONE_UID);
}
/**
@@ -947,11 +942,7 @@ public final class TelephonyPermissions {
* as system user or not.
*/
public static boolean isRootOrShell(int uid) {
- if (Flags.supportPhoneUidCheckForMultiuser()) {
- return UserHandle.isSameApp(uid, Process.ROOT_UID) || UserHandle.isSameApp(uid,
- Process.SHELL_UID);
- } else {
- return uid == Process.ROOT_UID || uid == Process.SHELL_UID;
- }
+ return UserHandle.isSameApp(uid, Process.ROOT_UID) || UserHandle.isSameApp(uid,
+ Process.SHELL_UID);
}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 13bd5eb67e44..aca0941cbcc5 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -10098,8 +10098,8 @@ public class CarrierConfigManager {
* The default value is 30 seconds.
*/
@FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
- public static final String KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT =
- "satellite_screen_off_inactivity_timeout_sec_int";
+ public static final String KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT =
+ "satellite_roaming_screen_off_inactivity_timeout_sec_int";
/**
* An integer key holds the timeout duration in seconds used to determine whether to exit P2P
@@ -10112,8 +10112,8 @@ public class CarrierConfigManager {
* The default value is 180 seconds.
*/
@FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
- public static final String KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT =
- "satellite_p2p_sms_inactivity_timeout_sec_int";
+ public static final String KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT =
+ "satellite_roaming_p2p_sms_inactivity_timeout_sec_int";
/**
* An integer key holds the timeout duration in seconds used to determine whether to exit ESOS
@@ -10126,8 +10126,8 @@ public class CarrierConfigManager {
* The default value is 600 seconds.
*/
@FlaggedApi(Flags.FLAG_CARRIER_ROAMING_NB_IOT_NTN)
- public static final String KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT =
- "satellite_esos_inactivity_timeout_sec_int";
+ public static final String KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT =
+ "satellite_roaming_esos_inactivity_timeout_sec_int";
/**
* Indicating whether DUN APN should be disabled when the device is roaming. In that case,
@@ -11294,9 +11294,9 @@ public class CarrierConfigManager {
sDefaults.putInt(KEY_CARRIER_ROAMING_NTN_EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_INT,
SatelliteManager.EMERGENCY_CALL_TO_SATELLITE_HANDOVER_TYPE_T911);
sDefaults.putInt(KEY_CARRIER_SUPPORTED_SATELLITE_NOTIFICATION_HYSTERESIS_SEC_INT, 180);
- sDefaults.putInt(KEY_SATELLITE_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT, 30);
- sDefaults.putInt(KEY_SATELLITE_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT, 180);
- sDefaults.putInt(KEY_SATELLITE_ESOS_INACTIVITY_TIMEOUT_SEC_INT, 600);
+ sDefaults.putInt(KEY_SATELLITE_ROAMING_SCREEN_OFF_INACTIVITY_TIMEOUT_SEC_INT, 30);
+ sDefaults.putInt(KEY_SATELLITE_ROAMING_P2P_SMS_INACTIVITY_TIMEOUT_SEC_INT, 180);
+ sDefaults.putInt(KEY_SATELLITE_ROAMING_ESOS_INACTIVITY_TIMEOUT_SEC_INT, 600);
sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
sDefaults.putBoolean(KEY_SUPPORTS_CALL_COMPOSER_BOOL, false);
sDefaults.putBoolean(KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, false);
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index bc709abbe76e..3ff1e2ca8dfb 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -23,6 +23,7 @@ import static android.provider.Telephony.Carriers.INVALID_APN_ID;
import static com.android.internal.util.Preconditions.checkNotNull;
import android.Manifest;
+import android.annotation.BoolRes;
import android.annotation.BytesLong;
import android.annotation.CallbackExecutor;
import android.annotation.CurrentTimeMillisLong;
@@ -6886,6 +6887,26 @@ public class TelephonyManager {
}
}
+ // Suppressing AndroidFrameworkCompatChange because we're querying vendor
+ // partition SDK level, not application's target SDK version.
+ @SuppressWarnings("AndroidFrameworkCompatChange")
+ private boolean hasCapability(@NonNull String feature, @BoolRes int legacySetting) {
+ if (mContext == null) return true;
+
+ if (mContext.getPackageManager().hasSystemFeature(feature)) return true;
+
+ // Check SDK version of the vendor partition.
+ final int vendorApiLevel = SystemProperties.getInt(
+ "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT);
+ // Devices shipped with 2024Q2 or later are required to declare FEATURE_TELEPHONY_*
+ // for individual sub-features (calling, messaging, data), so there's no need to check
+ // the legacy setting.
+ if (vendorApiLevel < Build.VENDOR_API_2024_Q2) {
+ return mContext.getResources().getBoolean(legacySetting);
+ }
+ return false;
+ }
+
// TODO(b/316183370): replace all @code with @link in javadoc after feature is released
/**
* @return true if the current device is "voice capable".
@@ -6905,11 +6926,9 @@ public class TelephonyManager {
* device (when {@code #isDeviceVoiceCapable} return {@code true}), caller should check for
* subscription-level voice capability as well. See {@code #isDeviceVoiceCapable} for details.
*/
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@Deprecated
public boolean isVoiceCapable() {
- if (mContext == null) return true;
- return mContext.getResources().getBoolean(
+ return hasCapability(PackageManager.FEATURE_TELEPHONY_CALLING,
com.android.internal.R.bool.config_voice_capable);
}
@@ -6932,7 +6951,6 @@ public class TelephonyManager {
*
* @see SubscriptionInfo#getServiceCapabilities()
*/
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_CALLING)
@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE)
public boolean isDeviceVoiceCapable() {
return isVoiceCapable();
@@ -6951,10 +6969,9 @@ public class TelephonyManager {
* device (when {@code #isDeviceSmsCapable} return {@code true}), caller should check for
* subscription-level SMS capability as well. See {@code #isDeviceSmsCapable} for details.
*/
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
+ @Deprecated
public boolean isSmsCapable() {
- if (mContext == null) return true;
- return mContext.getResources().getBoolean(
+ return hasCapability(PackageManager.FEATURE_TELEPHONY_MESSAGING,
com.android.internal.R.bool.config_sms_capable);
}
@@ -6974,7 +6991,6 @@ public class TelephonyManager {
*
* @see SubscriptionInfo#getServiceCapabilities()
*/
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_MESSAGING)
@FlaggedApi(Flags.FLAG_DATA_ONLY_CELLULAR_SERVICE)
public boolean isDeviceSmsCapable() {
return isSmsCapable();
@@ -14542,10 +14558,8 @@ public class TelephonyManager {
* data connections over the telephony network.
* <p>
*/
- @RequiresFeature(PackageManager.FEATURE_TELEPHONY_DATA)
public boolean isDataCapable() {
- if (mContext == null) return true;
- return mContext.getResources().getBoolean(
+ return hasCapability(PackageManager.FEATURE_TELEPHONY_DATA,
com.android.internal.R.bool.config_mobile_data_capable);
}
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 83fc0dcfe790..3944b8e0d0cc 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -412,6 +412,14 @@ public final class SatelliteManager {
@FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
public static final int SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS = 27;
+ /**
+ * Disabling satellite is in progress.
+ *
+ * @hide
+ */
+ @FlaggedApi(Flags.FLAG_OEM_ENABLED_SATELLITE_FLAG)
+ public static final int SATELLITE_RESULT_DISABLE_IN_PROGRESS = 28;
+
/** @hide */
@IntDef(prefix = {"SATELLITE_RESULT_"}, value = {
SATELLITE_RESULT_SUCCESS,
@@ -441,7 +449,8 @@ public final class SatelliteManager {
SATELLITE_RESULT_MODEM_TIMEOUT,
SATELLITE_RESULT_LOCATION_DISABLED,
SATELLITE_RESULT_LOCATION_NOT_AVAILABLE,
- SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS
+ SATELLITE_RESULT_EMERGENCY_CALL_IN_PROGRESS,
+ SATELLITE_RESULT_DISABLE_IN_PROGRESS
})
@Retention(RetentionPolicy.SOURCE)
public @interface SatelliteResult {}
diff --git a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
index 51154e5baee1..8b51321bc7c4 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
@@ -83,7 +83,16 @@ oneway interface ISatellite {
* is enabled, this may also disable the cellular modem, and if the satellite modem is disabled,
* this may also re-enable the cellular modem.
*
+ * Framework might send an enable request to update the enable attributes of an already-started
+ * satellite session. In such cases, modem needs to apply the new enable attrbitues to the
+ * satellite session. Moreover, modem needs to report its current state and signal strength
+ * level to framework right after receiving this request from framework.
+ *
+ * Framework might send a disable request when an enable request is being processed. In such
+ * cases, modem needs to abort the enable request and process the disable request.
+ *
* @param enableAttributes The enable parameters that will be applied to the satellite session
+ * @param resultCallback The callback to receive the error code result of the operation.
*
* Valid result codes returned:
* SatelliteResult:SATELLITE_RESULT_SUCCESS
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 29286e8f429e..b92ba6601044 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -169,13 +169,13 @@ public interface TelephonyProperties
/**
* Set to false to disable SMS receiving, default is
- * the value of config_sms_capable
+ * the value of TelephonyManager.isDeviceSmsCapable
*/
static final String PROPERTY_SMS_RECEIVE = "telephony.sms.receive";
/**
* Set to false to disable SMS sending, default is
- * the value of config_sms_capable
+ * the value of TelephonyManager.isDeviceSmsCapable
*/
static final String PROPERTY_SMS_SEND = "telephony.sms.send";
diff --git a/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewControllerTests.java b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewControllerTests.java
new file mode 100644
index 000000000000..c7ebd3a27a2e
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewControllerTests.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input.debug;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.hardware.input.InputManager;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableContext;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.InputDevice;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.input.InputManagerService;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+/**
+ * Build/Install/Run:
+ * atest TouchpadDebugViewControllerTests
+ */
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class TouchpadDebugViewControllerTests {
+ private static final int DEVICE_ID = 1000;
+ private static final String TAG = "TouchpadDebugViewController";
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ private Context mContext;
+ private TouchpadDebugViewController mTouchpadDebugViewController;
+ @Mock
+ private InputManager mInputManagerMock;
+ @Mock
+ private InputManagerService mInputManagerServiceMock;
+ @Mock
+ private WindowManager mWindowManagerMock;
+ private TestableLooper mTestableLooper;
+
+ @Before
+ public void setup() throws Exception {
+ mContext = InstrumentationRegistry.getInstrumentation().getContext();
+ TestableContext mTestableContext = new TestableContext(mContext);
+ mTestableContext.addMockSystemService(WindowManager.class, mWindowManagerMock);
+
+ Rect bounds = new Rect(0, 0, 2560, 1600);
+ WindowMetrics metrics = new WindowMetrics(bounds, new WindowInsets(bounds), 1.0f);
+
+ when(mWindowManagerMock.getCurrentWindowMetrics()).thenReturn(metrics);
+
+ unMockTouchpad();
+
+ mTestableLooper = TestableLooper.get(this);
+
+ mTestableContext.addMockSystemService(InputManager.class, mInputManagerMock);
+
+ mTouchpadDebugViewController = new TouchpadDebugViewController(mTestableContext,
+ mTestableLooper.getLooper(), mInputManagerServiceMock);
+ }
+
+ private InputDevice createTouchpadInputDevice(int id) {
+ return new InputDevice.Builder()
+ .setId(id)
+ .setSources(InputDevice.SOURCE_TOUCHPAD | InputDevice.SOURCE_MOUSE)
+ .setName("Test Device " + id)
+ .build();
+ }
+
+ private void mockTouchpad() {
+ when(mInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{DEVICE_ID});
+ when(mInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(
+ createTouchpadInputDevice(DEVICE_ID));
+ }
+
+ private void unMockTouchpad() {
+ when(mInputManagerMock.getInputDeviceIds()).thenReturn(new int[]{});
+ when(mInputManagerMock.getInputDevice(eq(DEVICE_ID))).thenReturn(null);
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingDisabled() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, never()).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+ }
+
+ @Test
+ public void settingEnabledWhileNoTouchpadConnected() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true);
+
+ verify(mWindowManagerMock, never()).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingEnabled() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingEnabledThenDisabled() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, times(1)).removeView(any());
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingDisabledThenEnabled() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, never()).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingDisabledThenTouchpadDisconnected() throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, never()).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+
+ unMockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceRemoved(DEVICE_ID);
+
+ verify(mWindowManagerMock, never()).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+ }
+
+ @Test
+ public void touchpadConnectedWhileSettingEnabledThenTouchpadDisconnectedThenSettingDisabled()
+ throws Exception {
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(true);
+
+ mockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceAdded(DEVICE_ID);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, never()).removeView(any());
+
+ unMockTouchpad();
+ mTouchpadDebugViewController.onInputDeviceRemoved(DEVICE_ID);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, times(1)).removeView(any());
+
+ mTouchpadDebugViewController.updateTouchpadVisualizerEnabled(false);
+
+ verify(mWindowManagerMock, times(1)).addView(any(), any());
+ verify(mWindowManagerMock, times(1)).removeView(any());
+ }
+}
diff --git a/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java
new file mode 100644
index 000000000000..ad0ef1b3a37f
--- /dev/null
+++ b/tests/Input/src/com/android/server/input/debug/TouchpadDebugViewTest.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.input.debug;
+
+import static android.view.InputDevice.SOURCE_TOUCHSCREEN;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.testing.TestableContext;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.cts.input.MotionEventBuilder;
+import com.android.cts.input.PointerBuilder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Build/Install/Run:
+ * atest TouchpadDebugViewTest
+ */
+@RunWith(AndroidJUnit4.class)
+public class TouchpadDebugViewTest {
+ private static final int TOUCHPAD_DEVICE_ID = 6;
+
+ private TouchpadDebugView mTouchpadDebugView;
+ private WindowManager.LayoutParams mWindowLayoutParams;
+
+ @Mock
+ WindowManager mWindowManager;
+
+ Rect mWindowBounds;
+ WindowMetrics mWindowMetrics;
+ TestableContext mTestableContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ Context context = InstrumentationRegistry.getInstrumentation().getContext();
+ mTestableContext = new TestableContext(context);
+
+ mTestableContext.addMockSystemService(WindowManager.class, mWindowManager);
+
+ mWindowBounds = new Rect(0, 0, 2560, 1600);
+ mWindowMetrics = new WindowMetrics(mWindowBounds, new WindowInsets(mWindowBounds), 1.0f);
+
+ when(mWindowManager.getCurrentWindowMetrics()).thenReturn(mWindowMetrics);
+
+ mTouchpadDebugView = new TouchpadDebugView(mTestableContext, TOUCHPAD_DEVICE_ID);
+
+ mTouchpadDebugView.measure(
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)
+ );
+
+ doAnswer(invocation -> {
+ mTouchpadDebugView.layout(0, 0, mTouchpadDebugView.getMeasuredWidth(),
+ mTouchpadDebugView.getMeasuredHeight());
+ return null;
+ }).when(mWindowManager).addView(any(), any());
+
+ doAnswer(invocation -> {
+ mTouchpadDebugView.layout(0, 0, mTouchpadDebugView.getMeasuredWidth(),
+ mTouchpadDebugView.getMeasuredHeight());
+ return null;
+ }).when(mWindowManager).updateViewLayout(any(), any());
+
+ mWindowLayoutParams = mTouchpadDebugView.getWindowLayoutParams();
+ mWindowLayoutParams.x = 20;
+ mWindowLayoutParams.y = 20;
+
+ mTouchpadDebugView.layout(0, 0, mTouchpadDebugView.getMeasuredWidth(),
+ mTouchpadDebugView.getMeasuredHeight());
+ }
+
+ @Test
+ public void testDragView() {
+ // Initial view position relative to screen.
+ int initialX = mWindowLayoutParams.x;
+ int initialY = mWindowLayoutParams.y;
+
+ float offsetX = ViewConfiguration.get(mTestableContext).getScaledTouchSlop() + 10;
+ float offsetY = ViewConfiguration.get(mTestableContext).getScaledTouchSlop() + 10;
+
+ // Simulate ACTION_DOWN event (initial touch).
+ MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(40f)
+ .y(40f)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+ verify(mWindowManager, times(0)).updateViewLayout(any(), any());
+
+ // Simulate ACTION_MOVE event (dragging to the right).
+ MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(40f + offsetX)
+ .y(40f + offsetY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+ ArgumentCaptor<WindowManager.LayoutParams> mWindowLayoutParamsCaptor =
+ ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+ verify(mWindowManager).updateViewLayout(any(), mWindowLayoutParamsCaptor.capture());
+
+ // Verify position after ACTION_MOVE
+ assertEquals(initialX + (long) offsetX, mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(initialY + (long) offsetY, mWindowLayoutParamsCaptor.getValue().y);
+
+ // Simulate ACTION_UP event (release touch).
+ MotionEvent actionUp = new MotionEventBuilder(MotionEvent.ACTION_UP, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(40f + offsetX)
+ .y(40f + offsetY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionUp);
+
+ assertEquals(initialX + (long) offsetX, mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(initialY + (long) offsetY, mWindowLayoutParamsCaptor.getValue().y);
+ }
+
+ @Test
+ public void testDragViewOutOfBounds() {
+ int initialX = mWindowLayoutParams.x;
+ int initialY = mWindowLayoutParams.y;
+
+ MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX + 10f)
+ .y(initialY + 10f)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+ verify(mWindowManager, times(0)).updateViewLayout(any(), any());
+
+ // Simulate ACTION_MOVE event (dragging far to the right and bottom, beyond screen bounds)
+ MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(mWindowBounds.width() + mTouchpadDebugView.getWidth())
+ .y(mWindowBounds.height() + mTouchpadDebugView.getHeight())
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+ ArgumentCaptor<WindowManager.LayoutParams> mWindowLayoutParamsCaptor =
+ ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+ verify(mWindowManager).updateViewLayout(any(), mWindowLayoutParamsCaptor.capture());
+
+ // Verify the view has been clamped to the right and bottom edges of the screen
+ assertEquals(mWindowBounds.width() - mTouchpadDebugView.getWidth(),
+ mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(mWindowBounds.height() - mTouchpadDebugView.getHeight(),
+ mWindowLayoutParamsCaptor.getValue().y);
+
+ MotionEvent actionUp = new MotionEventBuilder(MotionEvent.ACTION_UP, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(mWindowBounds.width() + mTouchpadDebugView.getWidth())
+ .y(mWindowBounds.height() + mTouchpadDebugView.getHeight())
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionUp);
+
+ // Verify the view has been clamped to the right and bottom edges of the screen
+ assertEquals(mWindowBounds.width() - mTouchpadDebugView.getWidth(),
+ mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(mWindowBounds.height() - mTouchpadDebugView.getHeight(),
+ mWindowLayoutParamsCaptor.getValue().y);
+ }
+
+ @Test
+ public void testSlopOffset() {
+ int initialX = mWindowLayoutParams.x;
+ int initialY = mWindowLayoutParams.y;
+
+ float offsetX = ViewConfiguration.get(mTestableContext).getScaledTouchSlop() / 2.0f;
+ float offsetY = -(ViewConfiguration.get(mTestableContext).getScaledTouchSlop() / 2.0f);
+
+ MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX)
+ .y(initialY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+ MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX + offsetX)
+ .y(initialY + offsetY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+ MotionEvent actionUp = new MotionEventBuilder(MotionEvent.ACTION_UP, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX)
+ .y(initialY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionUp);
+
+ // In this case the updateViewLayout() method wouldn't be called because the drag
+ // distance hasn't exceeded the slop
+ verify(mWindowManager, times(0)).updateViewLayout(any(), any());
+ }
+
+ @Test
+ public void testViewReturnsToInitialPositionOnCancel() {
+ int initialX = mWindowLayoutParams.x;
+ int initialY = mWindowLayoutParams.y;
+
+ float offsetX = 50;
+ float offsetY = 50;
+
+ MotionEvent actionDown = new MotionEventBuilder(MotionEvent.ACTION_DOWN, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX)
+ .y(initialY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionDown);
+
+ MotionEvent actionMove = new MotionEventBuilder(MotionEvent.ACTION_MOVE, SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX + offsetX)
+ .y(initialY + offsetY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionMove);
+
+ ArgumentCaptor<WindowManager.LayoutParams> mWindowLayoutParamsCaptor =
+ ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+ verify(mWindowManager).updateViewLayout(any(), mWindowLayoutParamsCaptor.capture());
+
+ assertEquals(initialX + (long) offsetX, mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(initialY + (long) offsetY, mWindowLayoutParamsCaptor.getValue().y);
+
+ // Simulate ACTION_CANCEL event (canceling the touch event stream)
+ MotionEvent actionCancel = new MotionEventBuilder(MotionEvent.ACTION_CANCEL,
+ SOURCE_TOUCHSCREEN)
+ .pointer(new PointerBuilder(0, MotionEvent.TOOL_TYPE_FINGER)
+ .x(initialX + offsetX)
+ .y(initialY + offsetY)
+ )
+ .build();
+ mTouchpadDebugView.dispatchTouchEvent(actionCancel);
+
+ // Verify the view returns to its initial position
+ verify(mWindowManager, times(2)).updateViewLayout(any(),
+ mWindowLayoutParamsCaptor.capture());
+ assertEquals(initialX, mWindowLayoutParamsCaptor.getValue().x);
+ assertEquals(initialY, mWindowLayoutParamsCaptor.getValue().y);
+ }
+}
diff --git a/tests/TrustTests/Android.bp b/tests/TrustTests/Android.bp
index 4e75a1d02a41..8888b32d2c69 100644
--- a/tests/TrustTests/Android.bp
+++ b/tests/TrustTests/Android.bp
@@ -40,3 +40,10 @@ android_test {
platform_apis: true,
certificate: "platform",
}
+
+test_module_config {
+ name: "TrustTests_trust_test",
+ base: "TrustTests",
+ test_suites: ["device-tests"],
+ include_filters: ["android.trust.test"],
+}