summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/statsd/src/atoms.proto20
-rw-r--r--core/java/android/app/ActivityThread.java1
-rw-r--r--core/java/android/app/ActivityView.java15
-rw-r--r--core/java/android/app/AppOpsManager.java25
-rw-r--r--core/java/android/app/ContextImpl.java25
-rw-r--r--core/java/android/app/IActivityManager.aidl10
-rw-r--r--core/java/android/app/Notification.java14
-rw-r--r--core/java/android/app/TaskInfo.java12
-rw-r--r--core/java/android/app/prediction/AppPredictor.java4
-rw-r--r--core/java/android/app/prediction/IPredictionManager.aidl2
-rw-r--r--core/java/android/content/pm/ActivityInfo.java6
-rw-r--r--core/java/android/content/pm/PackageInstaller.java5
-rw-r--r--core/java/android/content/pm/UserInfo.java10
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java14
-rw-r--r--core/java/android/os/BinderProxy.java14
-rwxr-xr-xcore/java/android/os/Build.java12
-rw-r--r--core/java/android/os/LocaleList.java11
-rw-r--r--core/java/android/os/Process.java2
-rw-r--r--core/java/android/os/storage/StorageManagerInternal.java2
-rwxr-xr-xcore/java/android/provider/Settings.java15
-rw-r--r--core/java/android/provider/Telephony.java13
-rw-r--r--core/java/android/view/InsetsState.java2
-rw-r--r--core/java/android/view/NotificationHeaderView.java25
-rw-r--r--core/java/android/view/ViewRootImpl.java31
-rw-r--r--core/java/android/view/WindowManager.java6
-rw-r--r--core/java/android/widget/ProgressBar.java8
-rw-r--r--core/java/android/window/VirtualDisplayTaskEmbedder.java9
-rw-r--r--core/java/com/android/internal/content/FileSystemProvider.java11
-rw-r--r--core/java/com/android/internal/widget/ConversationLayout.java44
-rw-r--r--core/java/com/android/internal/widget/LocalImageResolver.java17
-rw-r--r--core/jni/android_media_AudioTrack.cpp76
-rw-r--r--core/jni/android_util_Process.cpp17
-rw-r--r--core/proto/android/app/settings_enums.proto5
-rw-r--r--core/proto/android/providers/settings/secure.proto3
-rw-r--r--core/res/res/layout/notification_template_header.xml37
-rw-r--r--core/res/res/values-am/strings.xml4
-rw-r--r--core/res/res/values-ar/strings.xml26
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml4
-rw-r--r--core/res/res/values-be/strings.xml26
-rw-r--r--core/res/res/values-bs/strings.xml4
-rw-r--r--core/res/res/values-ca/strings.xml2
-rw-r--r--core/res/res/values-cs/strings.xml6
-rw-r--r--core/res/res/values-da/strings.xml2
-rw-r--r--core/res/res/values-es-rUS/strings.xml2
-rw-r--r--core/res/res/values-eu/strings.xml4
-rw-r--r--core/res/res/values-gl/strings.xml2
-rw-r--r--core/res/res/values-gu/strings.xml6
-rw-r--r--core/res/res/values-hu/strings.xml6
-rw-r--r--core/res/res/values-hy/strings.xml2
-rw-r--r--core/res/res/values-in/strings.xml4
-rw-r--r--core/res/res/values-kk/strings.xml6
-rw-r--r--core/res/res/values-km/strings.xml2
-rw-r--r--core/res/res/values-ky/strings.xml2
-rw-r--r--core/res/res/values-mn/strings.xml2
-rw-r--r--core/res/res/values-ne/strings.xml16
-rw-r--r--core/res/res/values-nl/strings.xml38
-rw-r--r--core/res/res/values-pa/strings.xml2
-rw-r--r--core/res/res/values-sr/strings.xml4
-rw-r--r--core/res/res/values-sv/strings.xml2
-rw-r--r--core/res/res/values-sw/strings.xml2
-rw-r--r--core/res/res/values-uz/strings.xml2
-rw-r--r--core/res/res/values/config.xml2
-rw-r--r--core/tests/coretests/AndroidManifest.xml1
-rw-r--r--core/tests/coretests/src/android/content/ContextTest.java38
-rw-r--r--core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java19
-rw-r--r--core/tests/coretests/src/android/view/InsetsStateTest.java20
-rw-r--r--core/tests/coretests/src/android/view/ViewRootImplTest.java11
-rw-r--r--data/etc/privapp-permissions-platform.xml1
-rw-r--r--location/java/android/location/LocationManager.java2
-rw-r--r--media/java/android/media/AudioTrack.java9
-rw-r--r--media/java/android/media/ExifInterface.java6
-rw-r--r--media/java/android/media/MediaPlayer.java5
-rw-r--r--media/java/android/media/PlayerBase.java5
-rw-r--r--media/jni/android_media_MediaPlayer.cpp9
-rw-r--r--packages/CarSystemUI/res-keyguard/layout/keyguard_password_view.xml2
-rw-r--r--packages/CarSystemUI/res/values/config.xml10
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java9
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java5
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java5
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java40
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java13
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java82
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java22
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBar.java224
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBarModule.java285
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java5
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java59
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java19
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java29
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java3
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java26
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java36
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java90
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayPanelViewControllerTest.java29
-rw-r--r--packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java156
-rw-r--r--packages/DynamicSystemInstallationService/res/values-nl/strings.xml2
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java7
-rw-r--r--packages/PackageInstaller/res/values-ar/strings.xml2
-rw-r--r--packages/PackageInstaller/res/values-nl/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-as/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-bn/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-fa/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-kn/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-ml/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-mr/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-or/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-te/strings.xml2
-rw-r--r--packages/PrintSpooler/res/values-uz/strings.xml2
-rw-r--r--packages/SettingsLib/HelpUtils/res/values-te/strings.xml2
-rw-r--r--packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_0.xml31
-rw-r--r--packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_1.xml27
-rw-r--r--packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_2.xml27
-rw-r--r--packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_3.xml27
-rw-r--r--packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_4.xml27
-rw-r--r--packages/SettingsLib/res/values-ar/strings.xml16
-rw-r--r--packages/SettingsLib/res/values-be/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-bs/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fa/strings.xml14
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-hy/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-in/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values-ja/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values-ky/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-mk/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-te/strings.xml2
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/Utils.java32
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java11
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java15
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java5
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java2
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java62
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java4
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java3
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/WriteFallbackSettingsFilesJobService.java22
-rw-r--r--packages/Shell/res/values-bn/strings.xml47
-rw-r--r--packages/Shell/res/values-eu/strings.xml47
-rw-r--r--packages/Shell/res/values-gl/strings.xml47
-rw-r--r--packages/Shell/res/values-is/strings.xml47
-rw-r--r--packages/Shell/res/values-ky/strings.xml47
-rw-r--r--packages/Shell/res/values-mk/strings.xml47
-rw-r--r--packages/Shell/res/values-ml/strings.xml47
-rw-r--r--packages/Shell/res/values-mr/strings.xml47
-rw-r--r--packages/Shell/res/values-my/strings.xml47
-rw-r--r--packages/Shell/res/values-ta/strings.xml47
-rw-r--r--packages/SoundPicker/res/values-ar/strings.xml2
-rw-r--r--packages/SoundPicker/res/values-cs/strings.xml8
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java5
-rw-r--r--packages/SystemUI/res-keyguard/values-ar/strings.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values-te/strings.xml2
-rw-r--r--packages/SystemUI/res-product/values-in/strings.xml8
-rw-r--r--packages/SystemUI/res/drawable-mcc310-mnc004/ic_5g_plus_mobiledata.xml36
-rw-r--r--packages/SystemUI/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml36
-rw-r--r--packages/SystemUI/res/layout/controls_management.xml5
-rw-r--r--packages/SystemUI/res/layout/controls_management_favorites.xml2
-rw-r--r--packages/SystemUI/res/layout/controls_structure_page.xml2
-rw-r--r--packages/SystemUI/res/values-af/strings.xml2
-rw-r--r--packages/SystemUI/res/values-am/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml18
-rw-r--r--packages/SystemUI/res/values-as/strings.xml2
-rw-r--r--packages/SystemUI/res/values-az/strings.xml4
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml2
-rw-r--r--packages/SystemUI/res/values-be/strings.xml4
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml4
-rw-r--r--packages/SystemUI/res/values-bn/strings.xml2
-rw-r--r--packages/SystemUI/res/values-bs/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml4
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml8
-rw-r--r--packages/SystemUI/res/values-da/strings.xml4
-rw-r--r--packages/SystemUI/res/values-de/strings.xml2
-rw-r--r--packages/SystemUI/res/values-el/strings.xml6
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rCA/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rXC/strings.xml2
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml12
-rw-r--r--packages/SystemUI/res/values-es/strings.xml12
-rw-r--r--packages/SystemUI/res/values-et/strings.xml2
-rw-r--r--packages/SystemUI/res/values-eu/strings.xml4
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml4
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml2
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-gl/strings.xml10
-rw-r--r--packages/SystemUI/res/values-gu/strings.xml4
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml8
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml4
-rw-r--r--packages/SystemUI/res/values-hy/strings.xml6
-rw-r--r--packages/SystemUI/res/values-in/strings.xml2
-rw-r--r--packages/SystemUI/res/values-is/strings.xml2
-rw-r--r--packages/SystemUI/res/values-it/strings.xml4
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ka/strings.xml4
-rw-r--r--packages/SystemUI/res/values-kk/strings.xml12
-rw-r--r--packages/SystemUI/res/values-km/strings.xml6
-rw-r--r--packages/SystemUI/res/values-kn/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ky/strings.xml6
-rw-r--r--packages/SystemUI/res/values-land/dimens.xml11
-rw-r--r--packages/SystemUI/res/values-lo/strings.xml2
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml4
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml4
-rw-r--r--packages/SystemUI/res/values-mcc310-mnc004/strings.xml22
-rw-r--r--packages/SystemUI/res/values-mcc311-mnc480/strings.xml22
-rw-r--r--packages/SystemUI/res/values-mk/strings.xml6
-rw-r--r--packages/SystemUI/res/values-ml/strings.xml2
-rw-r--r--packages/SystemUI/res/values-mn/strings.xml4
-rw-r--r--packages/SystemUI/res/values-mr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ms/strings.xml4
-rw-r--r--packages/SystemUI/res/values-my/strings.xml2
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ne/strings.xml12
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml12
-rw-r--r--packages/SystemUI/res/values-or/strings.xml4
-rw-r--r--packages/SystemUI/res/values-pa/strings.xml2
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml4
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml8
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml4
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml8
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml4
-rw-r--r--packages/SystemUI/res/values-si/strings.xml2
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml2
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml4
-rw-r--r--packages/SystemUI/res/values-sq/strings.xml4
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml2
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ta/strings.xml2
-rw-r--r--packages/SystemUI/res/values-te/strings.xml4
-rw-r--r--packages/SystemUI/res/values-th/strings.xml12
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml2
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml2
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml2
-rw-r--r--packages/SystemUI/res/values-ur/strings.xml2
-rw-r--r--packages/SystemUI/res/values-uz/strings.xml4
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml4
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml4
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml2
-rw-r--r--packages/SystemUI/res/values/dimens.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt157
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaData.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt79
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt74
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt204
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt41
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaHost.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt171
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java119
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipUiEventLogger.java33
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/PipWindowConfigurationCompact.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java83
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java214
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/Utils.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt48
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java82
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java22
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java23
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java108
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt162
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt47
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt124
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt422
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java144
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java230
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java42
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java26
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java1
-rw-r--r--services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java7
-rw-r--r--services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java135
-rw-r--r--services/core/java/android/os/UserManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java8
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java11
-rw-r--r--services/core/java/com/android/server/UiModeManagerService.java9
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java14
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java48
-rw-r--r--services/core/java/com/android/server/am/CachedAppOptimizer.java158
-rw-r--r--services/core/java/com/android/server/am/PendingTempWhitelists.java4
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java59
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java45
-rw-r--r--services/core/java/com/android/server/audio/AudioEventLogger.java31
-rwxr-xr-xservices/core/java/com/android/server/audio/AudioService.java142
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java45
-rw-r--r--services/core/java/com/android/server/biometrics/face/FaceService.java18
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java15
-rw-r--r--services/core/java/com/android/server/infra/AbstractMasterSystemService.java2
-rw-r--r--services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java28
-rw-r--r--services/core/java/com/android/server/location/LocationManagerService.java1
-rw-r--r--services/core/java/com/android/server/media/MediaSessionService.java21
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java13
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java115
-rw-r--r--services/core/java/com/android/server/pm/AppsFilter.java237
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java19
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java121
-rw-r--r--services/core/java/com/android/server/pm/Settings.java7
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java6
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java95
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java37
-rw-r--r--services/core/java/com/android/server/telecom/InternalServiceRepository.java63
-rw-r--r--services/core/java/com/android/server/telecom/TelecomLoaderService.java25
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java6
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerInternal.java23
-rw-r--r--services/core/java/com/android/server/uri/UriGrantsManagerService.java19
-rw-r--r--services/core/java/com/android/server/uri/UriPermissionOwner.java38
-rw-r--r--services/core/java/com/android/server/vr/Vr2dDisplay.java1
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityStack.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityStackSupervisor.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java26
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java58
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java85
-rw-r--r--services/core/java/com/android/server/wm/InsetsSourceProvider.java5
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java36
-rw-r--r--services/core/java/com/android/server/wm/LockTaskController.java44
-rw-r--r--services/core/java/com/android/server/wm/PolicyControl.java42
-rw-r--r--services/core/java/com/android/server/wm/RecentTasks.java3
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimationController.java8
-rw-r--r--services/core/java/com/android/server/wm/RootWindowContainer.java6
-rw-r--r--services/core/java/com/android/server/wm/SafeActivityOptions.java4
-rw-r--r--services/core/java/com/android/server/wm/Task.java19
-rw-r--r--services/core/java/com/android/server/wm/TaskOrganizerController.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java20
-rw-r--r--services/core/jni/Android.bp1
-rw-r--r--services/core/jni/com_android_server_am_CachedAppOptimizer.cpp56
-rw-r--r--services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java3
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java43
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java114
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java32
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java17
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java32
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java9
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java162
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java29
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java18
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java18
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java47
-rw-r--r--telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl26
-rw-r--r--telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl27
-rw-r--r--telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl28
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java59
-rw-r--r--telephony/java/android/telephony/CellIdentityNr.java12
-rw-r--r--telephony/java/android/telephony/CellInfoNr.java14
-rw-r--r--tests/RollbackTest/Android.bp3
-rw-r--r--tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java28
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java28
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java56
-rw-r--r--tests/utils/hostutils/src/com/android/tests/rollback/host/AbandonSessionsRule.java66
-rw-r--r--wifi/java/android/net/wifi/ScanResult.java21
-rw-r--r--wifi/java/android/net/wifi/WifiEnterpriseConfig.java49
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSpecifier.java31
-rw-r--r--wifi/java/android/net/wifi/WifiNetworkSuggestion.java31
-rw-r--r--wifi/tests/src/android/net/wifi/FakeKeys.java29
-rw-r--r--wifi/tests/src/android/net/wifi/ScanResultTest.java7
-rw-r--r--wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java17
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java192
-rw-r--r--wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java23
405 files changed, 7708 insertions, 2285 deletions
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 7d0d97917a4b..285eb4ac150e 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -3863,6 +3863,17 @@ message LmkStateChanged {
* system/core/lmkd/lmkd.c
*/
message LmkKillOccurred {
+ enum Reason {
+ UNKNOWN = 0;
+ PRESSURE_AFTER_KILL = 1;
+ NOT_RESPONDING = 2;
+ LOW_SWAP_AND_THRASHING = 3;
+ LOW_MEM_AND_SWAP = 4;
+ LOW_MEM_AND_THRASHING = 5;
+ DIRECT_RECL_AND_THRASHING = 6;
+ LOW_MEM_AND_SWAP_UTIL = 7;
+ }
+
// The uid if available. -1 means not available.
optional int32 uid = 1 [(is_uid) = true];
@@ -3892,6 +3903,15 @@ message LmkKillOccurred {
// Min oom adj score considered by lmkd.
optional int32 min_oom_score = 10;
+
+ // Free physical memory on device at LMK time.
+ optional int32 free_mem_kb = 11;
+
+ // Free swap on device at LMK time.
+ optional int32 free_swap_kb = 12;
+
+ // What triggered the LMK event.
+ optional Reason reason = 13;
}
/*
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 812ca4aefb9b..8d64661ef8a6 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5112,6 +5112,7 @@ public final class ActivityThread extends ClientTransactionHandler {
}
}
r.setState(ON_DESTROY);
+ mLastReportedWindowingMode.remove(r.activity.getActivityToken());
}
schedulePurgeIdler();
// updatePendingActivityConfiguration() reads from mActivities to update
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 98a23f2b0075..3cb6293f0706 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -105,7 +105,8 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
public ActivityView(
@NonNull Context context, @NonNull AttributeSet attrs, int defStyle,
boolean singleTaskInstance, boolean usePublicVirtualDisplay) {
- this(context, attrs, defStyle, singleTaskInstance, usePublicVirtualDisplay, false);
+ this(context, attrs, defStyle, singleTaskInstance, usePublicVirtualDisplay,
+ false /* disableSurfaceViewBackgroundLayer */);
}
/** @hide */
@@ -113,12 +114,22 @@ public class ActivityView extends ViewGroup implements android.window.TaskEmbedd
@NonNull Context context, @NonNull AttributeSet attrs, int defStyle,
boolean singleTaskInstance, boolean usePublicVirtualDisplay,
boolean disableSurfaceViewBackgroundLayer) {
+ this(context, attrs, defStyle, singleTaskInstance, usePublicVirtualDisplay,
+ disableSurfaceViewBackgroundLayer, false /* useTrustedDisplay */);
+ }
+
+ // TODO(b/162901735): Refactor ActivityView with Builder
+ /** @hide */
+ public ActivityView(
+ @NonNull Context context, @NonNull AttributeSet attrs, int defStyle,
+ boolean singleTaskInstance, boolean usePublicVirtualDisplay,
+ boolean disableSurfaceViewBackgroundLayer, boolean useTrustedDisplay) {
super(context, attrs, defStyle);
if (useTaskOrganizer()) {
mTaskEmbedder = new TaskOrganizerTaskEmbedder(context, this);
} else {
mTaskEmbedder = new VirtualDisplayTaskEmbedder(context, this, singleTaskInstance,
- usePublicVirtualDisplay);
+ usePublicVirtualDisplay, useTrustedDisplay);
}
mSurfaceView = new SurfaceView(context, null, 0, 0, disableSurfaceViewBackgroundLayer);
// Since ActivityView#getAlpha has been overridden, we should use parent class's alpha
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index d13137d4a716..eea5d62298fd 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1139,9 +1139,17 @@ public class AppOpsManager {
// TODO: Add as AppProtoEnums
public static final int OP_PHONE_CALL_CAMERA = 101;
+ /**
+ * Audio is being recorded for hotword detection.
+ *
+ * @hide
+ */
+ // TODO: Add as AppProtoEnums
+ public static final int OP_RECORD_AUDIO_HOTWORD = 102;
+
/** @hide */
@UnsupportedAppUsage
- public static final int _NUM_OP = 102;
+ public static final int _NUM_OP = 103;
/** Access to coarse location information. */
public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1472,6 +1480,13 @@ public class AppOpsManager {
*/
public static final String OPSTR_PHONE_CALL_CAMERA = "android:phone_call_camera";
+ /**
+ * Audio is being recorded for hotword detection.
+ *
+ * @hide
+ */
+ public static final String OPSTR_RECORD_AUDIO_HOTWORD = "android:record_audio_hotword";
+
/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
@@ -1663,6 +1678,7 @@ public class AppOpsManager {
OP_NO_ISOLATED_STORAGE, // NO_ISOLATED_STORAGE
OP_PHONE_CALL_MICROPHONE, // OP_PHONE_CALL_MICROPHONE
OP_PHONE_CALL_CAMERA, // OP_PHONE_CALL_CAMERA
+ OP_RECORD_AUDIO_HOTWORD, // RECORD_AUDIO_HOTWORD
};
/**
@@ -1771,6 +1787,7 @@ public class AppOpsManager {
OPSTR_NO_ISOLATED_STORAGE,
OPSTR_PHONE_CALL_MICROPHONE,
OPSTR_PHONE_CALL_CAMERA,
+ OPSTR_RECORD_AUDIO_HOTWORD,
};
/**
@@ -1880,6 +1897,7 @@ public class AppOpsManager {
"NO_ISOLATED_STORAGE",
"PHONE_CALL_MICROPHONE",
"PHONE_CALL_CAMERA",
+ "RECORD_AUDIO_HOTWORD",
};
/**
@@ -1990,6 +2008,7 @@ public class AppOpsManager {
null, // no permission for OP_NO_ISOLATED_STORAGE
null, // no permission for OP_PHONE_CALL_MICROPHONE
null, // no permission for OP_PHONE_CALL_CAMERA
+ null, // no permission for OP_RECORD_AUDIO_HOTWORD
};
/**
@@ -2100,6 +2119,7 @@ public class AppOpsManager {
null, // NO_ISOLATED_STORAGE
null, // PHONE_CALL_MICROPHONE
null, // PHONE_CALL_MICROPHONE
+ null, // RECORD_AUDIO_HOTWORD
};
/**
@@ -2209,6 +2229,7 @@ public class AppOpsManager {
null, // NO_ISOLATED_STORAGE
null, // PHONE_CALL_MICROPHONE
null, // PHONE_CALL_CAMERA
+ null, // RECORD_AUDIO_HOTWORD
};
/**
@@ -2317,6 +2338,7 @@ public class AppOpsManager {
AppOpsManager.MODE_ERRORED, // OP_NO_ISOLATED_STORAGE
AppOpsManager.MODE_ALLOWED, // PHONE_CALL_MICROPHONE
AppOpsManager.MODE_ALLOWED, // PHONE_CALL_CAMERA
+ AppOpsManager.MODE_ALLOWED, // OP_RECORD_AUDIO_HOTWORD
};
/**
@@ -2429,6 +2451,7 @@ public class AppOpsManager {
true, // NO_ISOLATED_STORAGE
false, // PHONE_CALL_MICROPHONE
false, // PHONE_CALL_CAMERA
+ false, // RECORD_AUDIO_HOTWORD
};
/**
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index d0fd92294979..c51a84649a07 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1914,10 +1914,8 @@ class ContextImpl extends Context {
@Override
public Object getSystemService(String name) {
if (vmIncorrectContextUseEnabled()) {
- // We may override this API from outer context.
- final boolean isUiContext = isUiContext() || isOuterUiContext();
// Check incorrect Context usage.
- if (isUiComponent(name) && !isUiContext) {
+ if (isUiComponent(name) && !isSelfOrOuterUiContext()) {
final String errorMessage = "Tried to access visual service "
+ SystemServiceRegistry.getSystemServiceClassName(name)
+ " from a non-visual Context:" + getOuterContext();
@@ -1934,15 +1932,17 @@ class ContextImpl extends Context {
return SystemServiceRegistry.getSystemService(this, name);
}
- private boolean isOuterUiContext() {
- return getOuterContext() != null && getOuterContext().isUiContext();
- }
-
@Override
public String getSystemServiceName(Class<?> serviceClass) {
return SystemServiceRegistry.getSystemServiceName(serviceClass);
}
+ // TODO(b/149463653): check if we still need this method after migrating IMS to WindowContext.
+ private boolean isSelfOrOuterUiContext() {
+ // We may override outer context's isUiContext
+ return isUiContext() || getOuterContext() != null && getOuterContext().isUiContext();
+ }
+
/** @hide */
@Override
public boolean isUiContext() {
@@ -2389,7 +2389,6 @@ class ContextImpl extends Context {
context.setResources(createResources(mToken, mPackageInfo, mSplitName, displayId,
overrideConfiguration, getDisplayAdjustments(displayId).getCompatibilityInfo(),
mResources.getLoaders()));
- context.mIsUiContext = isUiContext() || isOuterUiContext();
return context;
}
@@ -2409,6 +2408,11 @@ class ContextImpl extends Context {
mResources.getLoaders()));
context.mDisplay = display;
context.mIsAssociatedWithDisplay = true;
+ // Note that even if a display context is derived from an UI context, it should not be
+ // treated as UI context because it does not handle configuration changes from the server
+ // side. If the context does need to handle configuration changes, please use
+ // Context#createWindowContext(int, Bundle).
+ context.mIsUiContext = false;
return context;
}
@@ -2494,9 +2498,9 @@ class ContextImpl extends Context {
@Override
public Display getDisplay() {
- if (!mIsSystemOrSystemUiContext && !mIsAssociatedWithDisplay) {
+ if (!mIsSystemOrSystemUiContext && !mIsAssociatedWithDisplay && !isSelfOrOuterUiContext()) {
throw new UnsupportedOperationException("Tried to obtain display from a Context not "
- + "associated with one. Only visual Contexts (such as Activity or one created "
+ + "associated with one. Only visual Contexts (such as Activity or one created "
+ "with Context#createWindowContext) or ones created with "
+ "Context#createDisplayContext are associated with displays. Other types of "
+ "Contexts are typically related to background entities and may return an "
@@ -2770,6 +2774,7 @@ class ContextImpl extends Context {
mDisplay = container.mDisplay;
mIsAssociatedWithDisplay = container.mIsAssociatedWithDisplay;
mIsSystemOrSystemUiContext = container.mIsSystemOrSystemUiContext;
+ mIsUiContext = container.isSelfOrOuterUiContext();
} else {
mBasePackageName = packageInfo.mPackageName;
ApplicationInfo ainfo = packageInfo.getApplicationInfo();
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 2abe9cf9fce5..f98e26338063 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -684,4 +684,14 @@ interface IActivityManager {
* Kills uid with the reason of permission change.
*/
void killUidForPermissionChange(int appId, int userId, String reason);
+
+ /**
+ * Control the app freezer state. Returns true in case of success, false if the operation
+ * didn't succeed (for example, when the app freezer isn't supported).
+ * Handling the freezer state via this method is reentrant, that is it can be
+ * disabled and re-enabled multiple times in parallel. As long as there's a 1:1 disable to
+ * enable match, the freezer is re-enabled at last enable only.
+ * @param enable set it to true to enable the app freezer, false to disable it.
+ */
+ boolean enableAppFreezer(in boolean enable);
}
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index b95a402013ec..c273cf08d03b 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -207,7 +207,7 @@ public class Notification implements Parcelable
* <p>
* Avoids spamming the system with overly large strings such as full e-mails.
*/
- private static final int MAX_CHARSEQUENCE_LENGTH = 5 * 1024;
+ private static final int MAX_CHARSEQUENCE_LENGTH = 1024;
/**
* Maximum entries of reply text that are accepted by Builder and friends.
@@ -5151,10 +5151,18 @@ public class Notification implements Parcelable
bindHeaderChronometerAndTime(contentView, p);
bindProfileBadge(contentView, p);
bindAlertedIcon(contentView, p);
+ bindActivePermissions(contentView, p);
bindExpandButton(contentView, p);
mN.mUsesStandardHeader = true;
}
+ private void bindActivePermissions(RemoteViews contentView, StandardTemplateParams p) {
+ int color = getNeutralColor(p);
+ contentView.setDrawableTint(R.id.camera, false, color, PorterDuff.Mode.SRC_ATOP);
+ contentView.setDrawableTint(R.id.mic, false, color, PorterDuff.Mode.SRC_ATOP);
+ contentView.setDrawableTint(R.id.overlay, false, color, PorterDuff.Mode.SRC_ATOP);
+ }
+
private void bindExpandButton(RemoteViews contentView, StandardTemplateParams p) {
int color = isColorized(p) ? getPrimaryTextColor(p) : getSecondaryTextColor(p);
contentView.setDrawableTint(R.id.expand_button, false, color,
@@ -7821,7 +7829,7 @@ public class Notification implements Parcelable
*/
public Message(@NonNull CharSequence text, long timestamp, @Nullable Person sender,
boolean remoteInputHistory) {
- mText = text;
+ mText = safeCharSequence(text);
mTimestamp = timestamp;
mSender = sender;
mRemoteInputHistory = remoteInputHistory;
@@ -7935,7 +7943,7 @@ public class Notification implements Parcelable
bundle.putLong(KEY_TIMESTAMP, mTimestamp);
if (mSender != null) {
// Legacy listeners need this
- bundle.putCharSequence(KEY_SENDER, mSender.getName());
+ bundle.putCharSequence(KEY_SENDER, safeCharSequence(mSender.getName()));
bundle.putParcelable(KEY_SENDER_PERSON, mSender);
}
if (mDataMimeType != null) {
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index f3f00e50715b..f99d4e937f92 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -176,6 +176,13 @@ public class TaskInfo {
*/
public boolean isResizeable;
+ /**
+ * Screen orientation set by {@link #baseActivity} via
+ * {@link Activity#setRequestedOrientation(int)}.
+ * @hide
+ */
+ public @ActivityInfo.ScreenOrientation int requestedOrientation;
+
TaskInfo() {
// Do nothing
}
@@ -247,6 +254,7 @@ public class TaskInfo {
? ActivityInfo.CREATOR.createFromParcel(source)
: null;
isResizeable = source.readBoolean();
+ requestedOrientation = source.readInt();
}
/**
@@ -297,6 +305,7 @@ public class TaskInfo {
topActivityInfo.writeToParcel(dest, flags);
}
dest.writeBoolean(isResizeable);
+ dest.writeInt(requestedOrientation);
}
@Override
@@ -315,6 +324,7 @@ public class TaskInfo {
+ " token=" + token
+ " topActivityType=" + topActivityType
+ " pictureInPictureParams=" + pictureInPictureParams
- + " topActivityInfo=" + topActivityInfo;
+ + " topActivityInfo=" + topActivityInfo
+ + " requestedOrientation=" + requestedOrientation;
}
}
diff --git a/core/java/android/app/prediction/AppPredictor.java b/core/java/android/app/prediction/AppPredictor.java
index 7f436401dbf4..fa135b10ae1f 100644
--- a/core/java/android/app/prediction/AppPredictor.java
+++ b/core/java/android/app/prediction/AppPredictor.java
@@ -83,6 +83,8 @@ public final class AppPredictor {
private final AppPredictionSessionId mSessionId;
private final ArrayMap<Callback, CallbackWrapper> mRegisteredCallbacks = new ArrayMap<>();
+ private final IBinder mToken = new Binder();
+
/**
* Creates a new Prediction client.
* <p>
@@ -98,7 +100,7 @@ public final class AppPredictor {
mSessionId = new AppPredictionSessionId(
context.getPackageName() + ":" + UUID.randomUUID().toString(), context.getUserId());
try {
- mPredictionManager.createPredictionSession(predictionContext, mSessionId);
+ mPredictionManager.createPredictionSession(predictionContext, mSessionId, mToken);
} catch (RemoteException e) {
Log.e(TAG, "Failed to create predictor", e);
e.rethrowAsRuntimeException();
diff --git a/core/java/android/app/prediction/IPredictionManager.aidl b/core/java/android/app/prediction/IPredictionManager.aidl
index 587e3fd52377..863fc6f952dd 100644
--- a/core/java/android/app/prediction/IPredictionManager.aidl
+++ b/core/java/android/app/prediction/IPredictionManager.aidl
@@ -29,7 +29,7 @@ import android.content.pm.ParceledListSlice;
interface IPredictionManager {
void createPredictionSession(in AppPredictionContext context,
- in AppPredictionSessionId sessionId);
+ in AppPredictionSessionId sessionId, in IBinder token);
void notifyAppTargetEvent(in AppPredictionSessionId sessionId, in AppTargetEvent event);
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index bd02210259b8..31c77eeb5424 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -963,7 +963,7 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
/** @hide */
public static final int LOCK_TASK_LAUNCH_MODE_ALWAYS = 2;
/** @hide */
- public static final int LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED = 3;
+ public static final int LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED = 3;
/** @hide */
public static final String lockTaskLaunchModeToString(int lockTaskLaunchMode) {
@@ -974,8 +974,8 @@ public class ActivityInfo extends ComponentInfo implements Parcelable {
return "LOCK_TASK_LAUNCH_MODE_NEVER";
case LOCK_TASK_LAUNCH_MODE_ALWAYS:
return "LOCK_TASK_LAUNCH_MODE_ALWAYS";
- case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
- return "LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED";
+ case LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED:
+ return "LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED";
default:
return "unknown=" + lockTaskLaunchMode;
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index fc4ccd072e75..191c4655c708 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1291,9 +1291,8 @@ public class PackageInstaller {
*
* @throws PackageManager.NameNotFoundException if the new owner could not be found.
* @throws SecurityException if called after the session has been committed or abandoned.
- * @throws SecurityException if the session does not update the original installer
- * @throws SecurityException if streams opened through
- * {@link #openWrite(String, long, long) are still open.
+ * @throws IllegalArgumentException if streams opened through
+ * {@link #openWrite(String, long, long) are still open.
*/
public void transfer(@NonNull String packageName)
throws PackageManager.NameNotFoundException {
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index aca5b458a2d6..08b23b04f2ae 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -221,6 +221,14 @@ public class UserInfo implements Parcelable {
public boolean preCreated;
/**
+ * When {@code true}, it indicates this user was created by converting a {@link #preCreated}
+ * user.
+ *
+ * <p><b>NOTE: </b>only used for debugging purposes, it's not set when marshalled to a parcel.
+ */
+ public boolean convertedFromPreCreated;
+
+ /**
* Creates a UserInfo whose user type is determined automatically by the flags according to
* {@link #getDefaultUserType}; can only be used for user types handled there.
*/
@@ -413,6 +421,7 @@ public class UserInfo implements Parcelable {
lastLoggedInFingerprint = orig.lastLoggedInFingerprint;
partial = orig.partial;
preCreated = orig.preCreated;
+ convertedFromPreCreated = orig.convertedFromPreCreated;
profileGroupId = orig.profileGroupId;
restrictedProfileParentId = orig.restrictedProfileParentId;
guestToRemove = orig.guestToRemove;
@@ -440,6 +449,7 @@ public class UserInfo implements Parcelable {
+ ", type=" + userType
+ ", flags=" + flagsToString(flags)
+ (preCreated ? " (pre-created)" : "")
+ + (convertedFromPreCreated ? " (converted)" : "")
+ (partial ? " (partial)" : "")
+ "]";
}
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index c5a11abe1136..4f0c84e586a2 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -1208,15 +1208,19 @@ public class InputMethodService extends AbstractInputMethodService {
mWindow.getWindow().getAttributes().setFitInsetsIgnoringVisibility(true);
// IME layout should always be inset by navigation bar, no matter its current visibility,
- // unless automotive requests it, since automotive may hide the navigation bar.
+ // unless automotive requests it. Automotive devices may request the navigation bar to be
+ // hidden when the IME shows up (controlled via config_automotiveHideNavBarForKeyboard)
+ // in order to maximize the visible screen real estate. When this happens, the IME window
+ // should animate from the bottom of the screen to reduce the jank that happens from the
+ // lack of synchronization between the bottom system window and the IME window.
+ if (mIsAutomotive && mAutomotiveHideNavBarForKeyboard) {
+ mWindow.getWindow().setDecorFitsSystemWindows(false);
+ }
mWindow.getWindow().getDecorView().setOnApplyWindowInsetsListener(
(v, insets) -> v.onApplyWindowInsets(
new WindowInsets.Builder(insets).setInsets(
navigationBars(),
- mIsAutomotive && mAutomotiveHideNavBarForKeyboard
- ? android.graphics.Insets.NONE
- : insets.getInsetsIgnoringVisibility(navigationBars())
- )
+ insets.getInsetsIgnoringVisibility(navigationBars()))
.build()));
// For ColorView in DecorView to work, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS needs to be set
diff --git a/core/java/android/os/BinderProxy.java b/core/java/android/os/BinderProxy.java
index 683993f762c0..0185ba444ca4 100644
--- a/core/java/android/os/BinderProxy.java
+++ b/core/java/android/os/BinderProxy.java
@@ -18,6 +18,7 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.util.Log;
import android.util.SparseIntArray;
@@ -255,7 +256,12 @@ public final class BinderProxy implements IBinder {
// out of system_server to all processes hosting binder objects it holds a reference to;
// since some of those processes might be frozen, we don't want to block here
// forever. Disable the freezer.
- Process.enableFreezer(false);
+ try {
+ ActivityManager.getService().enableAppFreezer(false);
+ } catch (RemoteException e) {
+ Log.e(Binder.TAG, "RemoteException while disabling app freezer");
+ }
+
for (WeakReference<BinderProxy> weakRef : proxiesToQuery) {
BinderProxy bp = weakRef.get();
String key;
@@ -278,7 +284,11 @@ public final class BinderProxy implements IBinder {
counts.put(key, i + 1);
}
}
- Process.enableFreezer(true);
+ try {
+ ActivityManager.getService().enableAppFreezer(true);
+ } catch (RemoteException e) {
+ Log.e(Binder.TAG, "RemoteException while re-enabling app freezer");
+ }
Map.Entry<String, Integer>[] sorted = counts.entrySet().toArray(
new Map.Entry[counts.size()]);
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 49a1cb588a3e..bde332792e18 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1021,6 +1021,18 @@ public class Build {
/**
* R.
+ *
+ * <p>Applications targeting this or a later release will get these new changes in behavior.
+ * For more information about this release, see the
+ * <a href="/about/versions/11">Android 11 overview</a>.</p>
+ * <ul>
+ * <li><a href="/about/versions/11/behavior-changes-all">Behavior changes: all apps</a></li>
+ * <li><a href="/about/versions/11/behavior-changes-11">Behavior changes: Apps targeting
+ * Android 11</a></li>
+ * <li><a href="/about/versions/11/non-sdk-11">Updates to non-SDK interface restrictions
+ * in Android 11</a></li>
+ * </ul>
+ *
*/
public static final int R = 30;
}
diff --git a/core/java/android/os/LocaleList.java b/core/java/android/os/LocaleList.java
index ab4bb0b9f2cd..9c0bc45a346e 100644
--- a/core/java/android/os/LocaleList.java
+++ b/core/java/android/os/LocaleList.java
@@ -25,6 +25,7 @@ import android.icu.util.ULocale;
import com.android.internal.annotations.GuardedBy;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
@@ -151,18 +152,18 @@ public final class LocaleList implements Parcelable {
/**
* Creates a new {@link LocaleList}.
*
+ * If two or more same locales are passed, the repeated locales will be dropped.
* <p>For empty lists of {@link Locale} items it is better to use {@link #getEmptyLocaleList()},
* which returns a pre-constructed empty list.</p>
*
* @throws NullPointerException if any of the input locales is <code>null</code>.
- * @throws IllegalArgumentException if any of the input locales repeat.
*/
public LocaleList(@NonNull Locale... list) {
if (list.length == 0) {
mList = sEmptyList;
mStringRepresentation = "";
} else {
- final Locale[] localeList = new Locale[list.length];
+ final ArrayList<Locale> localeList = new ArrayList<>();
final HashSet<Locale> seenLocales = new HashSet<Locale>();
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.length; i++) {
@@ -170,10 +171,10 @@ public final class LocaleList implements Parcelable {
if (l == null) {
throw new NullPointerException("list[" + i + "] is null");
} else if (seenLocales.contains(l)) {
- throw new IllegalArgumentException("list[" + i + "] is a repetition");
+ // Dropping duplicated locale entries.
} else {
final Locale localeClone = (Locale) l.clone();
- localeList[i] = localeClone;
+ localeList.add(localeClone);
sb.append(localeClone.toLanguageTag());
if (i < list.length - 1) {
sb.append(',');
@@ -181,7 +182,7 @@ public final class LocaleList implements Parcelable {
seenLocales.add(localeClone);
}
}
- mList = localeList;
+ mList = localeList.toArray(new Locale[localeList.size()]);
mStringRepresentation = sb.toString();
}
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index a4077fbee892..efea9537c4cf 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -947,7 +947,7 @@ public class Process {
/**
* Enable or disable the freezer. When enable == false all frozen processes are unfrozen,
- * but aren't removed from the freezer. Processes can still be added or removed
+ * but aren't removed from the freezer. While in this state, processes can be added or removed
* by using setProcessFrozen, but they won't actually be frozen until the freezer is enabled
* again. If enable == true the freezer is enabled again, and all processes
* in the freezer (including the ones added while the freezer was disabled) are frozen.
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index e05991b33796..a79a1cfcd64f 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -118,7 +118,7 @@ public abstract class StorageManagerInternal {
* affects them.
*/
public abstract void onAppOpsChanged(int code, int uid,
- @Nullable String packageName, int mode);
+ @Nullable String packageName, int mode, int previousMode);
/**
* Asks the StorageManager to reset all state for the provided user; this will result
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index b5d0b78dcc76..8b45ba994d7e 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8929,14 +8929,6 @@ public final class Settings {
public static final String MEDIA_CONTROLS_RESUME = "qs_media_resumption";
/**
- * Controls which packages are blocked from persisting in media controls when resumption is
- * enabled. The list of packages is set by the user in the Settings app.
- * @see Settings.Secure#MEDIA_CONTROLS_RESUME
- * @hide
- */
- public static final String MEDIA_CONTROLS_RESUME_BLOCKED = "qs_media_resumption_blocked";
-
- /**
* Controls if window magnification is enabled.
* @hide
*/
@@ -8966,6 +8958,13 @@ public final class Settings {
public static final int ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW = 0x2;
/**
+ * Whether the Adaptive connectivity option is enabled.
+ *
+ * @hide
+ */
+ public static final String ADAPTIVE_CONNECTIVITY_ENABLED = "adaptive_connectivity_enabled";
+
+ /**
* Keys we no longer back up under the current schema, but want to continue to
* process when restoring historical backup datasets.
*
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index 2c66910529f1..718f2de33d5c 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -3954,9 +3954,7 @@ public final class Telephony {
public static final String APN_SET_ID = "apn_set_id";
/**
- * Possible value for the {@link #APN_SET_ID} field. By default APNs will not belong to a
- * set. If the user manually selects an APN without apn set id, there is no need to
- * prioritize any specific APN set ids.
+ * Possible value for the {@link #APN_SET_ID} field. By default APNs are added to set 0.
* <p>Type: INTEGER</p>
* @hide
*/
@@ -3964,6 +3962,15 @@ public final class Telephony {
public static final int NO_APN_SET_ID = 0;
/**
+ * Possible value for the {@link #APN_SET_ID} field.
+ * APNs with MATCH_ALL_APN_SET_ID will be used regardless of any set ids of
+ * the selected APN.
+ * <p>Type: INTEGER</p>
+ * @hide
+ */
+ public static final int MATCH_ALL_APN_SET_ID = -1;
+
+ /**
* A unique carrier id associated with this APN
* {@see TelephonyManager#getSimCarrierId()}
* <p>Type: STRING</p>
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 593b37af26ad..0b43547f03de 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -453,9 +453,11 @@ public class InsetsState implements Parcelable {
final ArraySet<Integer> result = new ArraySet<>();
if ((types & Type.STATUS_BARS) != 0) {
result.add(ITYPE_STATUS_BAR);
+ result.add(ITYPE_CLIMATE_BAR);
}
if ((types & Type.NAVIGATION_BARS) != 0) {
result.add(ITYPE_NAVIGATION_BAR);
+ result.add(ITYPE_EXTRA_NAVIGATION_BAR);
}
if ((types & Type.CAPTION_BAR) != 0) {
result.add(ITYPE_CAPTION_BAR);
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 7a467d6ad73f..0c50cb782c24 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -52,11 +52,13 @@ public class NotificationHeaderView extends ViewGroup {
private View mHeaderText;
private View mSecondaryHeaderText;
private OnClickListener mExpandClickListener;
+ private OnClickListener mAppOpsListener;
private HeaderTouchListener mTouchListener = new HeaderTouchListener();
private LinearLayout mTransferChip;
private NotificationExpandButton mExpandButton;
private CachingIconView mIcon;
private View mProfileBadge;
+ private View mAppOps;
private boolean mExpanded;
private boolean mShowExpandButtonAtEnd;
private boolean mShowWorkBadgeAtEnd;
@@ -113,6 +115,7 @@ public class NotificationHeaderView extends ViewGroup {
mExpandButton = findViewById(com.android.internal.R.id.expand_button);
mIcon = findViewById(com.android.internal.R.id.icon);
mProfileBadge = findViewById(com.android.internal.R.id.profile_badge);
+ mAppOps = findViewById(com.android.internal.R.id.app_ops);
}
@Override
@@ -140,6 +143,7 @@ public class NotificationHeaderView extends ViewGroup {
// Icons that should go at the end
if ((child == mExpandButton && mShowExpandButtonAtEnd)
|| child == mProfileBadge
+ || child == mAppOps
|| child == mTransferChip) {
iconWidth += lp.leftMargin + lp.rightMargin + child.getMeasuredWidth();
} else {
@@ -204,6 +208,7 @@ public class NotificationHeaderView extends ViewGroup {
// Icons that should go at the end
if ((child == mExpandButton && mShowExpandButtonAtEnd)
|| child == mProfileBadge
+ || child == mAppOps
|| child == mTransferChip) {
if (end == getMeasuredWidth()) {
layoutRight = end - mContentEndMargin;
@@ -272,10 +277,22 @@ public class NotificationHeaderView extends ViewGroup {
}
private void updateTouchListener() {
+ if (mExpandClickListener == null && mAppOpsListener == null) {
+ setOnTouchListener(null);
+ return;
+ }
setOnTouchListener(mTouchListener);
mTouchListener.bindTouchRects();
}
+ /**
+ * Sets onclick listener for app ops icons.
+ */
+ public void setAppOpsOnClickListener(OnClickListener l) {
+ mAppOpsListener = l;
+ updateTouchListener();
+ }
+
@Override
public void setOnClickListener(@Nullable OnClickListener l) {
mExpandClickListener = l;
@@ -363,6 +380,7 @@ public class NotificationHeaderView extends ViewGroup {
private final ArrayList<Rect> mTouchRects = new ArrayList<>();
private Rect mExpandButtonRect;
+ private Rect mAppOpsRect;
private int mTouchSlop;
private boolean mTrackGesture;
private float mDownX;
@@ -375,6 +393,8 @@ public class NotificationHeaderView extends ViewGroup {
mTouchRects.clear();
addRectAroundView(mIcon);
mExpandButtonRect = addRectAroundView(mExpandButton);
+ mAppOpsRect = addRectAroundView(mAppOps);
+ setTouchDelegate(new TouchDelegate(mAppOpsRect, mAppOps));
addWidthRect();
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
@@ -435,6 +455,11 @@ public class NotificationHeaderView extends ViewGroup {
break;
case MotionEvent.ACTION_UP:
if (mTrackGesture) {
+ if (mAppOps.isVisibleToUser() && (mAppOpsRect.contains((int) x, (int) y)
+ || mAppOpsRect.contains((int) mDownX, (int) mDownY))) {
+ mAppOps.performClick();
+ return true;
+ }
mExpandButton.performClick();
}
break;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index bcf3b49c6644..4a56761bbce5 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -53,6 +53,9 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_APPEARANCE_CO
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
@@ -1449,14 +1452,13 @@ public final class ViewRootImpl implements ViewParent,
}
// Don't lose the mode we last auto-computed.
- if ((attrs.softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
+ if ((attrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
== WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
mWindowAttributes.softInputMode = (mWindowAttributes.softInputMode
- & ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
- | (oldSoftInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST);
+ & ~SOFT_INPUT_MASK_ADJUST) | (oldSoftInputMode & SOFT_INPUT_MASK_ADJUST);
}
- if ((changes & LayoutParams.SOFT_INPUT_MODE_CHANGED) != 0) {
+ if (mWindowAttributes.softInputMode != oldSoftInputMode) {
requestFitSystemWindows();
}
@@ -2073,6 +2075,7 @@ public final class ViewRootImpl implements ViewParent,
final int sysUiVis = inOutParams.systemUiVisibility | inOutParams.subtreeSystemUiVisibility;
final int flags = inOutParams.flags;
final int type = inOutParams.type;
+ final int adjust = inOutParams.softInputMode & SOFT_INPUT_MASK_ADJUST;
if ((inOutParams.privateFlags & PRIVATE_FLAG_APPEARANCE_CONTROLLED) == 0) {
inOutParams.insetsFlags.appearance = 0;
@@ -2098,12 +2101,13 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ inOutParams.privateFlags &= ~PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
+
if ((inOutParams.privateFlags & PRIVATE_FLAG_FIT_INSETS_CONTROLLED) != 0) {
return;
}
int types = inOutParams.getFitInsetsTypes();
- int sides = inOutParams.getFitInsetsSides();
boolean ignoreVis = inOutParams.isFitInsetsIgnoringVisibility();
if (((sysUiVis & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) != 0
@@ -2118,10 +2122,13 @@ public final class ViewRootImpl implements ViewParent,
if (type == TYPE_TOAST || type == TYPE_SYSTEM_ALERT) {
ignoreVis = true;
} else if ((types & Type.systemBars()) == Type.systemBars()) {
- types |= Type.ime();
+ if (adjust == SOFT_INPUT_ADJUST_RESIZE) {
+ types |= Type.ime();
+ } else {
+ inOutParams.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
+ }
}
inOutParams.setFitInsetsTypes(types);
- inOutParams.setFitInsetsSides(sides);
inOutParams.setFitInsetsIgnoringVisibility(ignoreVis);
// The fitting of insets are not really controlled by the clients, so we remove the flag.
@@ -2491,8 +2498,7 @@ public final class ViewRootImpl implements ViewParent,
if (mFirst || mAttachInfo.mViewVisibilityChanged) {
mAttachInfo.mViewVisibilityChanged = false;
- int resizeMode = mSoftInputMode &
- WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
+ int resizeMode = mSoftInputMode & SOFT_INPUT_MASK_ADJUST;
// If we are in auto resize mode, then we need to determine
// what mode to use now.
if (resizeMode == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
@@ -2505,11 +2511,8 @@ public final class ViewRootImpl implements ViewParent,
if (resizeMode == 0) {
resizeMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
}
- if ((lp.softInputMode &
- WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) != resizeMode) {
- lp.softInputMode = (lp.softInputMode &
- ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST) |
- resizeMode;
+ if ((lp.softInputMode & SOFT_INPUT_MASK_ADJUST) != resizeMode) {
+ lp.softInputMode = (lp.softInputMode & ~SOFT_INPUT_MASK_ADJUST) | resizeMode;
params = lp;
}
}
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 5c6269421a1f..2a711f6974f3 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -2033,6 +2033,12 @@ public interface WindowManager extends ViewManager {
public static final int PRIVATE_FLAG_FIT_INSETS_CONTROLLED = 0x10000000;
/**
+ * Flag to indicate that the parent frame of a window should be inset by IME.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME = 0x40000000;
+
+ /**
* An internal annotation for flags that can be specified to {@link #softInputMode}.
*
* @hide
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 970d70cf1fb4..f56c357c57a8 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -52,6 +52,7 @@ import android.view.View;
import android.view.ViewDebug;
import android.view.ViewHierarchyEncoder;
import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
@@ -306,9 +307,6 @@ public class ProgressBar extends View {
setMax(a.getInt(R.styleable.ProgressBar_max, mMax));
setProgress(a.getInt(R.styleable.ProgressBar_progress, mProgress));
- // onProgressRefresh() is only called when the progress changes. So we should set
- // stateDescription during initialization here.
- super.setStateDescription(formatStateDescription(mProgress));
setSecondaryProgress(a.getInt(
R.styleable.ProgressBar_secondaryProgress, mSecondaryProgress));
@@ -1601,7 +1599,8 @@ public class ProgressBar extends View {
}
void onProgressRefresh(float scale, boolean fromUser, int progress) {
- if (mCustomStateDescription == null) {
+ if (AccessibilityManager.getInstance(mContext).isEnabled()
+ && mCustomStateDescription == null) {
super.setStateDescription(formatStateDescription(mProgress));
}
}
@@ -2325,6 +2324,7 @@ public class ProgressBar extends View {
AccessibilityNodeInfo.RangeInfo.RANGE_TYPE_INT, getMin(), getMax(),
getProgress());
info.setRangeInfo(rangeInfo);
+ info.setStateDescription(formatStateDescription(mProgress));
}
}
diff --git a/core/java/android/window/VirtualDisplayTaskEmbedder.java b/core/java/android/window/VirtualDisplayTaskEmbedder.java
index 9ccb4c172158..9013da36007e 100644
--- a/core/java/android/window/VirtualDisplayTaskEmbedder.java
+++ b/core/java/android/window/VirtualDisplayTaskEmbedder.java
@@ -19,6 +19,7 @@ package android.window;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
+import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
import static android.view.Display.INVALID_DISPLAY;
import android.app.ActivityManager;
@@ -63,6 +64,7 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder {
private int mDisplayDensityDpi;
private final boolean mSingleTaskInstance;
private final boolean mUsePublicVirtualDisplay;
+ private final boolean mUseTrustedDisplay;
private VirtualDisplay mVirtualDisplay;
private Insets mForwardedInsets;
private DisplayMetrics mTmpDisplayMetrics;
@@ -77,10 +79,12 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder {
* only applicable if virtual displays are used
*/
public VirtualDisplayTaskEmbedder(Context context, VirtualDisplayTaskEmbedder.Host host,
- boolean singleTaskInstance, boolean usePublicVirtualDisplay) {
+ boolean singleTaskInstance, boolean usePublicVirtualDisplay,
+ boolean useTrustedDisplay) {
super(context, host);
mSingleTaskInstance = singleTaskInstance;
mUsePublicVirtualDisplay = usePublicVirtualDisplay;
+ mUseTrustedDisplay = useTrustedDisplay;
}
/**
@@ -103,6 +107,9 @@ public class VirtualDisplayTaskEmbedder extends TaskEmbedder {
if (mUsePublicVirtualDisplay) {
virtualDisplayFlags |= VIRTUAL_DISPLAY_FLAG_PUBLIC;
}
+ if (mUseTrustedDisplay) {
+ virtualDisplayFlags |= VIRTUAL_DISPLAY_FLAG_TRUSTED;
+ }
mVirtualDisplay = displayManager.createVirtualDisplay(
DISPLAY_NAME + "@" + System.identityHashCode(this), mHost.getWidth(),
diff --git a/core/java/com/android/internal/content/FileSystemProvider.java b/core/java/com/android/internal/content/FileSystemProvider.java
index a50a52219c74..3b5fecfc600a 100644
--- a/core/java/com/android/internal/content/FileSystemProvider.java
+++ b/core/java/com/android/internal/content/FileSystemProvider.java
@@ -113,6 +113,14 @@ public abstract class FileSystemProvider extends DocumentsProvider {
// Default is no-op
}
+ /**
+ * Callback indicating that the given document has been deleted or moved. This gives
+ * the provider a hook to revoke the uri permissions.
+ */
+ protected void onDocIdDeleted(String docId) {
+ // Default is no-op
+ }
+
@Override
public boolean onCreate() {
throw new UnsupportedOperationException(
@@ -283,6 +291,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
final String afterDocId = getDocIdForFile(after);
onDocIdChanged(docId);
+ onDocIdDeleted(docId);
onDocIdChanged(afterDocId);
final File afterVisibleFile = getFileForDocId(afterDocId, true);
@@ -312,6 +321,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
final String docId = getDocIdForFile(after);
onDocIdChanged(sourceDocumentId);
+ onDocIdDeleted(sourceDocumentId);
onDocIdChanged(docId);
moveInMediaStore(visibleFileBefore, getFileForDocId(docId, true));
@@ -343,6 +353,7 @@ public abstract class FileSystemProvider extends DocumentsProvider {
}
onDocIdChanged(docId);
+ onDocIdDeleted(docId);
removeFromMediaStore(visibleFile);
}
diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java
index e3a456cc94a4..0791ed3c42ec 100644
--- a/core/java/com/android/internal/widget/ConversationLayout.java
+++ b/core/java/com/android/internal/widget/ConversationLayout.java
@@ -167,6 +167,8 @@ public class ConversationLayout extends FrameLayout
private int mFacePileProtectionWidthExpanded;
private boolean mImportantConversation;
private TextView mUnreadBadge;
+ private ViewGroup mAppOps;
+ private Rect mAppOpsTouchRect = new Rect();
private float mMinTouchSize;
private Icon mConversationIcon;
private Icon mShortcutIcon;
@@ -208,6 +210,7 @@ public class ConversationLayout extends FrameLayout
mConversationIconView = findViewById(R.id.conversation_icon);
mConversationIconContainer = findViewById(R.id.conversation_icon_container);
mIcon = findViewById(R.id.icon);
+ mAppOps = findViewById(com.android.internal.R.id.app_ops);
mMinTouchSize = 48 * getResources().getDisplayMetrics().density;
mImportanceRingView = findViewById(R.id.conversation_icon_badge_ring);
mConversationIconBadge = findViewById(R.id.conversation_icon_badge);
@@ -1163,6 +1166,47 @@ public class ConversationLayout extends FrameLayout
}
});
}
+ if (mAppOps.getWidth() > 0) {
+
+ // Let's increase the touch size of the app ops view if it's here
+ mAppOpsTouchRect.set(
+ mAppOps.getLeft(),
+ mAppOps.getTop(),
+ mAppOps.getRight(),
+ mAppOps.getBottom());
+ for (int i = 0; i < mAppOps.getChildCount(); i++) {
+ View child = mAppOps.getChildAt(i);
+ if (child.getVisibility() == GONE) {
+ continue;
+ }
+ // Make sure each child has at least a minTouchSize touch target around it
+ float childTouchLeft = child.getLeft() + child.getWidth() / 2.0f
+ - mMinTouchSize / 2.0f;
+ float childTouchRight = childTouchLeft + mMinTouchSize;
+ mAppOpsTouchRect.left = (int) Math.min(mAppOpsTouchRect.left,
+ mAppOps.getLeft() + childTouchLeft);
+ mAppOpsTouchRect.right = (int) Math.max(mAppOpsTouchRect.right,
+ mAppOps.getLeft() + childTouchRight);
+ }
+
+ // Increase the height
+ int heightIncrease = 0;
+ if (mAppOpsTouchRect.height() < mMinTouchSize) {
+ heightIncrease = (int) Math.ceil((mMinTouchSize - mAppOpsTouchRect.height())
+ / 2.0f);
+ }
+ mAppOpsTouchRect.inset(0, -heightIncrease);
+
+ // Let's adjust the hitrect since app ops isn't a direct child
+ ViewGroup viewGroup = (ViewGroup) mAppOps.getParent();
+ while (viewGroup != this) {
+ mAppOpsTouchRect.offset(viewGroup.getLeft(), viewGroup.getTop());
+ viewGroup = (ViewGroup) viewGroup.getParent();
+ }
+ //
+ // Extend the size of the app opps to be at least 48dp
+ setTouchDelegate(new TouchDelegate(mAppOpsTouchRect, mAppOps));
+ }
}
public MessagingLinearLayout getMessagingLinearLayout() {
diff --git a/core/java/com/android/internal/widget/LocalImageResolver.java b/core/java/com/android/internal/widget/LocalImageResolver.java
index 2302de2cd058..b4e108faee2d 100644
--- a/core/java/com/android/internal/widget/LocalImageResolver.java
+++ b/core/java/com/android/internal/widget/LocalImageResolver.java
@@ -23,6 +23,7 @@ import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
+import android.util.Log;
import java.io.IOException;
import java.io.InputStream;
@@ -31,6 +32,7 @@ import java.io.InputStream;
* A class to extract Bitmaps from a MessagingStyle message.
*/
public class LocalImageResolver {
+ private static final String TAG = LocalImageResolver.class.getSimpleName();
private static final int MAX_SAFE_ICON_SIZE_PX = 480;
@@ -60,11 +62,18 @@ public class LocalImageResolver {
private static BitmapFactory.Options getBoundsOptionsForImage(Uri uri, Context context)
throws IOException {
- InputStream input = context.getContentResolver().openInputStream(uri);
BitmapFactory.Options onlyBoundsOptions = new BitmapFactory.Options();
- onlyBoundsOptions.inJustDecodeBounds = true;
- BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
- input.close();
+ try (InputStream input = context.getContentResolver().openInputStream(uri)) {
+ if (input == null) {
+ throw new IllegalArgumentException();
+ }
+ onlyBoundsOptions.inJustDecodeBounds = true;
+ BitmapFactory.decodeStream(input, null, onlyBoundsOptions);
+ } catch (IllegalArgumentException iae) {
+ onlyBoundsOptions.outWidth = -1;
+ onlyBoundsOptions.outHeight = -1;
+ Log.e(TAG, "error loading image", iae);
+ }
return onlyBoundsOptions;
}
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 5c045b65be22..7a5c38385f32 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -20,6 +20,7 @@
#include "android_media_AudioTrack.h"
#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
#include "core_jni_helpers.h"
#include <utils/Log.h>
@@ -251,7 +252,7 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
jint audioFormat, jint buffSizeInBytes, jint memoryMode,
jintArray jSession, jlong nativeAudioTrack,
jboolean offload, jint encapsulationMode,
- jobject tunerConfiguration) {
+ jobject tunerConfiguration, jstring opPackageName) {
ALOGV("sampleRates=%p, channel mask=%x, index mask=%x, audioFormat(Java)=%d, buffSize=%d,"
" nativeAudioTrack=0x%" PRIX64 ", offload=%d encapsulationMode=%d tuner=%p",
jSampleRate, channelPositionMask, channelIndexMask, audioFormat, buffSizeInBytes,
@@ -337,7 +338,8 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
}
// create the native AudioTrack object
- lpTrack = new AudioTrack();
+ ScopedUtfChars opPackageNameStr(env, opPackageName);
+ lpTrack = new AudioTrack(opPackageNameStr.c_str());
// read the AudioAttributes values
auto paa = JNIAudioAttributeHelper::makeUnique();
@@ -371,23 +373,24 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
status_t status = NO_ERROR;
switch (memoryMode) {
case MODE_STREAM:
- status = lpTrack->set(
- AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
- sampleRateInHertz,
- format,// word length, PCM
- nativeChannelMask,
- offload ? 0 : frameCount,
- offload ? AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD : AUDIO_OUTPUT_FLAG_NONE,
- audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user)
- 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
- 0,// shared mem
- true,// thread can call Java
- sessionId,// audio session ID
- offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK : AudioTrack::TRANSFER_SYNC,
- offload ? &offloadInfo : NULL,
- -1, -1, // default uid, pid values
- paa.get());
-
+ status = lpTrack->set(AUDIO_STREAM_DEFAULT, // stream type, but more info conveyed
+ // in paa (last argument)
+ sampleRateInHertz,
+ format, // word length, PCM
+ nativeChannelMask, offload ? 0 : frameCount,
+ offload ? AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD
+ : AUDIO_OUTPUT_FLAG_NONE,
+ audioCallback,
+ &(lpJniStorage->mCallbackData), // callback, callback data (user)
+ 0, // notificationFrames == 0 since not using EVENT_MORE_DATA
+ // to feed the AudioTrack
+ 0, // shared mem
+ true, // thread can call Java
+ sessionId, // audio session ID
+ offload ? AudioTrack::TRANSFER_SYNC_NOTIF_CALLBACK
+ : AudioTrack::TRANSFER_SYNC,
+ offload ? &offloadInfo : NULL, -1, -1, // default uid, pid values
+ paa.get());
break;
case MODE_STATIC:
@@ -398,22 +401,22 @@ static jint android_media_AudioTrack_setup(JNIEnv *env, jobject thiz, jobject we
goto native_init_failure;
}
- status = lpTrack->set(
- AUDIO_STREAM_DEFAULT,// stream type, but more info conveyed in paa (last argument)
- sampleRateInHertz,
- format,// word length, PCM
- nativeChannelMask,
- frameCount,
- AUDIO_OUTPUT_FLAG_NONE,
- audioCallback, &(lpJniStorage->mCallbackData),//callback, callback data (user));
- 0,// notificationFrames == 0 since not using EVENT_MORE_DATA to feed the AudioTrack
- lpJniStorage->mMemBase,// shared mem
- true,// thread can call Java
- sessionId,// audio session ID
- AudioTrack::TRANSFER_SHARED,
- NULL, // default offloadInfo
- -1, -1, // default uid, pid values
- paa.get());
+ status = lpTrack->set(AUDIO_STREAM_DEFAULT, // stream type, but more info conveyed
+ // in paa (last argument)
+ sampleRateInHertz,
+ format, // word length, PCM
+ nativeChannelMask, frameCount, AUDIO_OUTPUT_FLAG_NONE,
+ audioCallback,
+ &(lpJniStorage->mCallbackData), // callback, callback data (user)
+ 0, // notificationFrames == 0 since not using EVENT_MORE_DATA
+ // to feed the AudioTrack
+ lpJniStorage->mMemBase, // shared mem
+ true, // thread can call Java
+ sessionId, // audio session ID
+ AudioTrack::TRANSFER_SHARED,
+ NULL, // default offloadInfo
+ -1, -1, // default uid, pid values
+ paa.get());
break;
default:
@@ -1428,7 +1431,8 @@ static const JNINativeMethod gMethods[] = {
{"native_stop", "()V", (void *)android_media_AudioTrack_stop},
{"native_pause", "()V", (void *)android_media_AudioTrack_pause},
{"native_flush", "()V", (void *)android_media_AudioTrack_flush},
- {"native_setup", "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZILjava/lang/Object;)I",
+ {"native_setup",
+ "(Ljava/lang/Object;Ljava/lang/Object;[IIIIII[IJZILjava/lang/Object;Ljava/lang/String;)I",
(void *)android_media_AudioTrack_setup},
{"native_finalize", "()V", (void *)android_media_AudioTrack_finalize},
{"native_release", "()V", (void *)android_media_AudioTrack_release},
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 7c32ca653114..6becb07d02a4 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -346,22 +346,6 @@ void android_os_Process_setProcessFrozen(
}
}
-void android_os_Process_enableFreezer(
- JNIEnv *env, jobject clazz, jboolean enable)
-{
- bool success = true;
-
- if (enable) {
- success = SetTaskProfiles(0, {"FreezerFrozen"}, true);
- } else {
- success = SetTaskProfiles(0, {"FreezerThawed"}, true);
- }
-
- if (!success) {
- jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
- }
-}
-
jint android_os_Process_getProcessGroup(JNIEnv* env, jobject clazz, jint pid)
{
SchedPolicy sp;
@@ -1360,7 +1344,6 @@ static const JNINativeMethod methods[] = {
{"sendSignal", "(II)V", (void*)android_os_Process_sendSignal},
{"sendSignalQuiet", "(II)V", (void*)android_os_Process_sendSignalQuiet},
{"setProcessFrozen", "(IIZ)V", (void*)android_os_Process_setProcessFrozen},
- {"enableFreezer", "(Z)V", (void*)android_os_Process_enableFreezer},
{"getFreeMemory", "()J", (void*)android_os_Process_getFreeMemory},
{"getTotalMemory", "()J", (void*)android_os_Process_getTotalMemory},
{"readProcLines", "(Ljava/lang/String;[Ljava/lang/String;[J)V",
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 69b32c264d3d..2cfd6105fcd4 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2683,4 +2683,9 @@ enum PageId {
// CATEGORY: SETTINGS
// OS: R
MEDIA_CONTROLS_SETTINGS = 1845;
+
+ // OPEN: Settings > Network & internet > Adaptive connectivity
+ // CATEGORY: SETTINGS
+ // OS: R QPR
+ ADAPTIVE_CONNECTIVITY_CATEGORY = 1850;
}
diff --git a/core/proto/android/providers/settings/secure.proto b/core/proto/android/providers/settings/secure.proto
index fe8a0f183546..acf8cc4944d9 100644
--- a/core/proto/android/providers/settings/secure.proto
+++ b/core/proto/android/providers/settings/secure.proto
@@ -180,6 +180,7 @@ message SecureSettingsProto {
optional SettingProto cmas_additional_broadcast_pkg = 14 [ (android.privacy).dest = DEST_AUTOMATIC ];
repeated SettingProto completed_categories = 15;
optional SettingProto connectivity_release_pending_intent_delay_ms = 16 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto adaptive_connectivity_enabled = 84 [ (android.privacy).dest = DEST_AUTOMATIC ];
message Controls {
option (android.msg_privacy).dest = DEST_EXPLICIT;
@@ -595,5 +596,5 @@ message SecureSettingsProto {
// Please insert fields in alphabetical order and group them into messages
// if possible (to avoid reaching the method limit).
- // Next tag = 82;
+ // Next tag = 85;
}
diff --git a/core/res/res/layout/notification_template_header.xml b/core/res/res/layout/notification_template_header.xml
index 03e130e8023b..23b8bd34829e 100644
--- a/core/res/res/layout/notification_template_header.xml
+++ b/core/res/res/layout/notification_template_header.xml
@@ -146,6 +146,43 @@
android:visibility="gone"
android:contentDescription="@string/notification_work_profile_content_description"
/>
+ <LinearLayout
+ android:id="@+id/app_ops"
+ android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_marginStart="6dp"
+ android:background="?android:selectableItemBackgroundBorderless"
+ android:orientation="horizontal">
+ <ImageView
+ android:id="@+id/camera"
+ android:layout_width="?attr/notificationHeaderIconSize"
+ android:layout_height="?attr/notificationHeaderIconSize"
+ android:src="@drawable/ic_camera"
+ android:visibility="gone"
+ android:focusable="false"
+ android:contentDescription="@string/notification_appops_camera_active"
+ />
+ <ImageView
+ android:id="@+id/mic"
+ android:layout_width="?attr/notificationHeaderIconSize"
+ android:layout_height="?attr/notificationHeaderIconSize"
+ android:src="@drawable/ic_mic"
+ android:layout_marginStart="4dp"
+ android:visibility="gone"
+ android:focusable="false"
+ android:contentDescription="@string/notification_appops_microphone_active"
+ />
+ <ImageView
+ android:id="@+id/overlay"
+ android:layout_width="?attr/notificationHeaderIconSize"
+ android:layout_height="?attr/notificationHeaderIconSize"
+ android:src="@drawable/ic_alert_window_layer"
+ android:layout_marginStart="4dp"
+ android:visibility="gone"
+ android:focusable="false"
+ android:contentDescription="@string/notification_appops_overlay_active"
+ />
+ </LinearLayout>
<include
layout="@layout/notification_material_media_transfer_action"
android:id="@+id/media_seamless"
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index ea8498ab33da..57f2d6aea741 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1216,7 +1216,7 @@
<string name="dump_heap_ready_text" msgid="5849618132123045516">"የ<xliff:g id="PROC">%1$s</xliff:g> ሂደት ተራጋፊ ክምር ለማጋራት ለእርስዎ ይገኛል። ይጠንቀቁ፦ ይህ ተራጋፊ ክምር ሂደቱ ሊደርስባቸው የሚችለው ማንኛውም የግል መረጃ ሊኖረው ይችላል፣ ይህ እርስዎ የተየቧቸውን ነገሮች ሊያካትት ይችላል።"</string>
<string name="sendText" msgid="493003724401350724">"ለፅሁፍ ድርጊት ምረጥ"</string>
<string name="volume_ringtone" msgid="134784084629229029">"የስልክ ጥሪ ድምፅ"</string>
- <string name="volume_music" msgid="7727274216734955095">" ማህደረ መረጃ ክፍልፍል"</string>
+ <string name="volume_music" msgid="7727274216734955095">"የማህደረ መረጃ ድምጽ መጠን"</string>
<string name="volume_music_hint_playing_through_bluetooth" msgid="2614142915948898228">"በብሉቱዝ በኩል ማጫወት"</string>
<string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"የፀጥታ የስልክ የደውል ድምፅ ተዘጋጅቷል"</string>
<string name="volume_call" msgid="7625321655265747433">"የጥሪ ላይ ድም ፅ መጨመሪያ/መቀነሻ"</string>
@@ -1227,7 +1227,7 @@
<string name="volume_icon_description_bluetooth" msgid="7540388479345558400">"የብሉቱዝ ድምፅ መጠን"</string>
<string name="volume_icon_description_ringer" msgid="2187800636867423459">"የስልክ ጥሪ ድምፅ መጠን"</string>
<string name="volume_icon_description_incall" msgid="4491255105381227919">"የስልክ ጥሪ ድምፅ መጠን"</string>
- <string name="volume_icon_description_media" msgid="4997633254078171233">"የማህደረ መረጃ ክፍልፍል"</string>
+ <string name="volume_icon_description_media" msgid="4997633254078171233">"የማህደረ መረጃ ድምጽ መጠን"</string>
<string name="volume_icon_description_notification" msgid="579091344110747279">"የማሳወቂያ ክፍልፍል"</string>
<string name="ringtone_default" msgid="9118299121288174597">"ነባሪ የስልክ ላይ ጥሪ"</string>
<string name="ringtone_default_with_actual" msgid="2709686194556159773">"ነባሪ (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 6978a9aefb17..4a99ec8021e8 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -270,9 +270,9 @@
<string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"وضع صامت"</string>
<string name="global_action_silent_mode_on_status" msgid="2371892537738632013">"الصوت متوقف"</string>
<string name="global_action_silent_mode_off_status" msgid="6608006545950920042">"الصوت قيد التفعيل"</string>
- <string name="global_actions_toggle_airplane_mode" msgid="6911684460146916206">"وضع الطائرة"</string>
- <string name="global_actions_airplane_mode_on_status" msgid="5508025516695361936">"وضع الطائرة قيد التفعيل"</string>
- <string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"وضع الطائرة متوقف"</string>
+ <string name="global_actions_toggle_airplane_mode" msgid="6911684460146916206">"وضع الطيران"</string>
+ <string name="global_actions_airplane_mode_on_status" msgid="5508025516695361936">"وضع الطيران قيد التفعيل"</string>
+ <string name="global_actions_airplane_mode_off_status" msgid="8522219771500505475">"وضع الطيران متوقف"</string>
<string name="global_action_settings" msgid="4671878836947494217">"الإعدادات"</string>
<string name="global_action_assist" msgid="2517047220311505805">"مساعدة"</string>
<string name="global_action_voice_assist" msgid="6655788068555086695">"المساعد الصوتي"</string>
@@ -398,7 +398,7 @@
<string name="permlab_getPackageSize" msgid="375391550792886641">"قياس مساحة تخزين التطبيق"</string>
<string name="permdesc_getPackageSize" msgid="742743530909966782">"للسماح للتطبيق باسترداد شفرته وبياناته وأحجام ذاكرات التخزين المؤقت"</string>
<string name="permlab_writeSettings" msgid="8057285063719277394">"تعديل إعدادات النظام"</string>
- <string name="permdesc_writeSettings" msgid="8293047411196067188">"للسماح للتطبيق بتعديل بيانات إعدادات النظام. يمكن أن تتلف التطبيقات الضارة تهيئة نظامك."</string>
+ <string name="permdesc_writeSettings" msgid="8293047411196067188">"للسماح للتطبيق بتعديل بيانات إعدادات النظام. يمكن أن تتلف التطبيقات الضارة إعداد نظامك."</string>
<string name="permlab_receiveBootCompleted" msgid="6643339400247325379">"العمل عند بدء التشغيل"</string>
<string name="permdesc_receiveBootCompleted" product="tablet" msgid="5565659082718177484">"للسماح للتطبيق ببدء تشغيل نفسه عقب انتهاء النظام من التشغيل. قد يؤدي ذلك إلى استغراق المزيد من الوقت عند بدء الجهاز اللوحي والسماح للتطبيق بإبطاء الأداء الإجمالي للجهاز اللوحي من خلال تشغيله دائمًا."</string>
<string name="permdesc_receiveBootCompleted" product="tv" msgid="4900842256047614307">"‏للسماح بتشغيل التطبيق تلقائيًا بعد الانتهاء من بدء تشغيل النظام. وقد يؤدي ذلك إلى إطالة فترة بدء تشغيل جهاز Android TV، بالإضافة إلى أنه يسمح للتطبيق بإبطاء أداء الجهاز بشكل عام لأنه يتم تشغيله بشكل دائم."</string>
@@ -507,7 +507,7 @@
<string name="permlab_accessWifiState" msgid="5552488500317911052">"‏عرض اتصالات Wi-Fi"</string>
<string name="permdesc_accessWifiState" msgid="6913641669259483363">"‏للسماح للتطبيق بعرض معلومات حول شبكات Wi-Fi، كعرض معلومات حول ما إذا تم تفعيل Wi-Fi واسم أجهزة Wi-Fi المتصلة."</string>
<string name="permlab_changeWifiState" msgid="7947824109713181554">"‏التوصيل والفصل من Wi-Fi"</string>
- <string name="permdesc_changeWifiState" msgid="7170350070554505384">"‏للسماح للتطبيق بالاتصال بنقاط الوصول إلى Wi-Fi وقطع الاتصال بها، وإجراء تغييرات على تهيئة الجهاز لشبكات Wi-Fi."</string>
+ <string name="permdesc_changeWifiState" msgid="7170350070554505384">"‏للسماح للتطبيق بالاتصال بنقاط الوصول إلى Wi-Fi وقطع الاتصال بها، وإجراء تغييرات على إعداد الجهاز لشبكات Wi-Fi."</string>
<string name="permlab_changeWifiMulticastState" msgid="285626875870754696">"‏السماح باستقبال بث Wi-Fi متعدد"</string>
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="191079868596433554">"‏للسماح للتطبيق بتلقي الحزم التي يتم إرسالها إلى جميع الأجهزة على شبكة Wi-Fi باستخدام عناوين بث متعدد، وليس باستخدام جهازك اللوحي فقط. ويؤدي ذلك إلى استخدام قدر أكبر من الطاقة يفوق وضع البث غير المتعدد."</string>
<string name="permdesc_changeWifiMulticastState" product="tv" msgid="1336952358450652595">"‏للسماح للتطبيق بتلقّي الحِزم التي يتم إرسالها إلى جميع الأجهزة على شبكة Wi-Fi باستخدام عناوين بث متعدد، وليس باستخدام جهاز Android TV فقط. ويؤدي ذلك إلى استخدام قدر أكبر من الطاقة يفوق ما يتم استهلاكه في وضع البث غير المتعدد."</string>
@@ -523,9 +523,9 @@
<string name="permdesc_changeWimaxState" product="tv" msgid="5373274458799425276">"‏للسماح للتطبيق بتوصيل جهاز Android TV بشبكات WiMAX وقطع اتصاله بها."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="1551666203780202101">"‏للسماح للتطبيق بتوصيل الهاتف بشبكات WiMAX وقطع اتصاله بها."</string>
<string name="permlab_bluetooth" msgid="586333280736937209">"الاتصال بأجهزة بلوتوث"</string>
- <string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"للسماح للتطبيق بعرض تهيئة البلوتوث على الجهاز اللوحي وإجراء اتصالات وقبولها مع الأجهزة المقترنة."</string>
+ <string name="permdesc_bluetooth" product="tablet" msgid="3053222571491402635">"للسماح للتطبيق بعرض إعداد البلوتوث على الجهاز اللوحي وإجراء اتصالات وقبولها مع الأجهزة المقترنة."</string>
<string name="permdesc_bluetooth" product="tv" msgid="8851534496561034998">"‏للسماح للتطبيق بعرض بيانات ضبط البلوتوث على جهاز Android TV وإجراء اتصالات مع الأجهزة المقترنة وقبولها."</string>
- <string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"للسماح للتطبيق بعرض تهيئة البلوتوث على الهاتف وإجراء اتصالات وقبولها مع الأجهزة المقترنة."</string>
+ <string name="permdesc_bluetooth" product="default" msgid="2779606714091276746">"للسماح للتطبيق بعرض إعداد البلوتوث على الهاتف وإجراء اتصالات وقبولها مع الأجهزة المقترنة."</string>
<string name="permlab_preferredPaymentInfo" msgid="5274423844767445054">"‏معلومات الخدمات المدفوعة باستخدام الاتصال قصير المدى NFC المفضّل"</string>
<string name="permdesc_preferredPaymentInfo" msgid="8583552469807294967">"‏يسمح هذا الإذن للتطبيق بالحصول على معلومات الخدمات المدفوعة باستخدام الاتصال قصير المدى NFC المفضّل، مثلاً المساعدات المسجّلة ووجهة المسار."</string>
<string name="permlab_nfc" msgid="1904455246837674977">"التحكم في اتصال الحقل القريب"</string>
@@ -661,8 +661,8 @@
<string name="permdesc_bindConditionProviderService" msgid="6106018791256120258">"للسماح للمالك بالربط بواجهة المستوى العلوي لخدمة موفر الحالة. لن تكون هناك حاجة إلى هذا الإعداد مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_bindDreamService" msgid="4776175992848982706">"‏الالتزام بخدمة dream"</string>
<string name="permdesc_bindDreamService" msgid="9129615743300572973">"‏للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة dream. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
- <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"استدعاء تطبيق التهيئة الذي يوفره مشغل شبكة الجوال"</string>
- <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"للسماح للمالك باستدعاء تطبيق التهيئة الذي يوفره مشغل شبكة الجوال. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+ <string name="permlab_invokeCarrierSetup" msgid="5098810760209818140">"استدعاء تطبيق الإعداد الذي يوفره مشغل شبكة الجوال"</string>
+ <string name="permdesc_invokeCarrierSetup" msgid="4790845896063237887">"للسماح للمالك باستدعاء تطبيق الإعداد الذي يوفره مشغل شبكة الجوال. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"الاستماع إلى ملاحظات حول أحوال الشبكة"</string>
<string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"للسماح للتطبيق بالاستماع إلى ملاحظات حول أحوال الشبكة. لا حاجة إلى هذا مع التطبيقات العادية."</string>
<string name="permlab_setInputCalibration" msgid="932069700285223434">"تغيير معايرة أجهزة الإدخال"</string>
@@ -678,7 +678,7 @@
<string name="permlab_bindCarrierServices" msgid="2395596978626237474">"الالتزام بخدمات مشغل شبكة الجوال"</string>
<string name="permdesc_bindCarrierServices" msgid="9185614481967262900">"للسماح للمالك بالالتزام بخدمات مشغل شبكة الجوال. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_access_notification_policy" msgid="5524112842876975537">"الوصول إلى إعداد \"عدم الإزعاج\""</string>
- <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"للسماح للتطبيق بقراءة تهيئة \"عدم الإزعاج\" وكتابتها."</string>
+ <string name="permdesc_access_notification_policy" msgid="8538374112403845013">"للسماح للتطبيق بقراءة إعداد \"عدم الإزعاج\" وكتابتها."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"بدء استخدام إذن العرض"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"للسماح للمالك ببدء استخدام الإذن لأحد التطبيقات. ولن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"تعيين قواعد كلمة المرور"</string>
@@ -1298,7 +1298,7 @@
<string name="volume_ringtone" msgid="134784084629229029">"مستوى صوت الرنين"</string>
<string name="volume_music" msgid="7727274216734955095">"مستوى صوت الوسائط"</string>
<string name="volume_music_hint_playing_through_bluetooth" msgid="2614142915948898228">"تشغيل من خلال البلوتوث"</string>
- <string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"تم تعيين نغمة الرنين الصامتة"</string>
+ <string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"تم ضبط نغمة الرنين الصامتة"</string>
<string name="volume_call" msgid="7625321655265747433">"مستوى صوت المكالمات الواردة"</string>
<string name="volume_bluetooth_call" msgid="2930204618610115061">"مستوى صوت المكالمة الواردة بالبلوتوث"</string>
<string name="volume_alarm" msgid="4486241060751798448">"مستوى صوت المنبّه"</string>
@@ -1462,7 +1462,7 @@
<string name="ext_media_status_unmountable" msgid="7043574843541087748">"تالف"</string>
<string name="ext_media_status_unsupported" msgid="5460509911660539317">"غير متوافق"</string>
<string name="ext_media_status_ejecting" msgid="7532403368044013797">"جارٍ إنهاء التحميل…"</string>
- <string name="ext_media_status_formatting" msgid="774148701503179906">"جارٍ التهيئة…"</string>
+ <string name="ext_media_status_formatting" msgid="774148701503179906">"تجري التهيئة..."</string>
<string name="ext_media_status_missing" msgid="6520746443048867314">"لم يتم الإدخال"</string>
<string name="activity_list_empty" msgid="4219430010716034252">"لم يتم العثور على أي أنشطة متطابقة."</string>
<string name="permlab_route_media_output" msgid="8048124531439513118">"توجيه إخراج الوسائط"</string>
@@ -2155,7 +2155,7 @@
<string name="mime_type_spreadsheet_ext" msgid="8720173181137254414">"جدول بيانات: <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
<string name="mime_type_presentation" msgid="1145384236788242075">"عرض تقديمي"</string>
<string name="mime_type_presentation_ext" msgid="8761049335564371468">"عرض تقديمي: <xliff:g id="EXTENSION">%1$s</xliff:g>"</string>
- <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"سيظل البلوتوث مفعَّلاً أثناء استخدام \"وضع الطائرة\"."</string>
+ <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"سيظل البلوتوث مفعَّلاً أثناء استخدام \"وضع الطيران\"."</string>
<string name="car_loading_profile" msgid="8219978381196748070">"جارٍ التحميل"</string>
<plurals name="file_count" formatted="false" msgid="7063513834724389247">
<item quantity="zero"><xliff:g id="FILE_NAME_2">%s</xliff:g> و<xliff:g id="COUNT_3">%d</xliff:g> ملف</item>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 18b69875b901..40fe31d873b2 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -241,7 +241,7 @@
<string name="global_action_power_off" msgid="4404936470711393203">"Isključi"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"Napajanje"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Restartuj"</string>
- <string name="global_action_emergency" msgid="1387617624177105088">"Hitni poziv"</string>
+ <string name="global_action_emergency" msgid="1387617624177105088">"Hitan poziv"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Izveštaj o grešci"</string>
<string name="global_action_logout" msgid="6093581310002476511">"Završi sesiju"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"Snimak ekrana"</string>
@@ -832,7 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Pritisnite „Meni“ da biste otključali telefon ili uputite hitan poziv."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Pritisnite „Meni“ za otključavanje."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Unesite šablon za otključavanje"</string>
- <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Hitni poziv"</string>
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Hitan poziv"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Nazad na poziv"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Tačno!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Probajte ponovo"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index 74f0e68f5f3f..df7fca0bc6e1 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -717,10 +717,10 @@
<item msgid="6216981255272016212">"Асаблівы"</item>
</string-array>
<string-array name="emailAddressTypes">
- <item msgid="7786349763648997741">"Хатні"</item>
- <item msgid="435564470865989199">"Працоўны"</item>
- <item msgid="4199433197875490373">"Іншы"</item>
- <item msgid="3233938986670468328">"Карыстальніцкі"</item>
+ <item msgid="7786349763648997741">"Асабістая"</item>
+ <item msgid="435564470865989199">"Працоўная"</item>
+ <item msgid="4199433197875490373">"Іншая"</item>
+ <item msgid="3233938986670468328">"Карыстальніцкая"</item>
</string-array>
<string-array name="postalAddressTypes">
<item msgid="3861463339764243038">"На Галоўную старонку"</item>
@@ -770,14 +770,14 @@
<string name="phoneTypeWorkPager" msgid="3748332310638505234">"Працоўны пэйджар"</string>
<string name="phoneTypeAssistant" msgid="757550783842231039">"Асістэнт"</string>
<string name="phoneTypeMms" msgid="1799747455131365989">"MMS"</string>
- <string name="eventTypeCustom" msgid="3257367158986466481">"Карыстальніцкі"</string>
+ <string name="eventTypeCustom" msgid="3257367158986466481">"Карыстальніцкае"</string>
<string name="eventTypeBirthday" msgid="7770026752793912283">"Дзень нараджэння"</string>
<string name="eventTypeAnniversary" msgid="4684702412407916888">"Гадавіна"</string>
<string name="eventTypeOther" msgid="530671238533887997">"Іншае"</string>
- <string name="emailTypeCustom" msgid="1809435350482181786">"Карыстальніцкі"</string>
+ <string name="emailTypeCustom" msgid="1809435350482181786">"Карыстальніцкая"</string>
<string name="emailTypeHome" msgid="1597116303154775999">"Хатні"</string>
- <string name="emailTypeWork" msgid="2020095414401882111">"Працоўны"</string>
- <string name="emailTypeOther" msgid="5131130857030897465">"Іншы"</string>
+ <string name="emailTypeWork" msgid="2020095414401882111">"Працоўная"</string>
+ <string name="emailTypeOther" msgid="5131130857030897465">"Іншая"</string>
<string name="emailTypeMobile" msgid="787155077375364230">"Мабільны"</string>
<string name="postalTypeCustom" msgid="5645590470242939129">"Карыстальніцкі"</string>
<string name="postalTypeHome" msgid="7562272480949727912">"Хатні"</string>
@@ -800,19 +800,19 @@
<string name="orgTypeWork" msgid="8684458700669564172">"Працоўная"</string>
<string name="orgTypeOther" msgid="5450675258408005553">"Іншая"</string>
<string name="orgTypeCustom" msgid="1126322047677329218">"Карыстальніцкі"</string>
- <string name="relationTypeCustom" msgid="282938315217441351">"Карыстальніцкі"</string>
+ <string name="relationTypeCustom" msgid="282938315217441351">"Карыстальніцкае"</string>
<string name="relationTypeAssistant" msgid="4057605157116589315">"Памочнік"</string>
<string name="relationTypeBrother" msgid="7141662427379247820">"Брат"</string>
<string name="relationTypeChild" msgid="9076258911292693601">"Дзіця"</string>
- <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"Унутраны Партнёр"</string>
+ <string name="relationTypeDomesticPartner" msgid="7825306887697559238">"Сужыцель/сужыцелька"</string>
<string name="relationTypeFather" msgid="3856225062864790596">"Бацька"</string>
<string name="relationTypeFriend" msgid="3192092625893980574">"Сябар/сяброўка"</string>
<string name="relationTypeManager" msgid="2272860813153171857">"Кіраўнік"</string>
<string name="relationTypeMother" msgid="2331762740982699460">"Маці"</string>
- <string name="relationTypeParent" msgid="4177920938333039882">"Бацька"</string>
+ <string name="relationTypeParent" msgid="4177920938333039882">"Бацька/маці"</string>
<string name="relationTypePartner" msgid="4018017075116766194">"Партнёр"</string>
- <string name="relationTypeReferredBy" msgid="5285082289602849400">"Запрошаны"</string>
- <string name="relationTypeRelative" msgid="3396498519818009134">"Адносны"</string>
+ <string name="relationTypeReferredBy" msgid="5285082289602849400">"Рэкамендацыя"</string>
+ <string name="relationTypeRelative" msgid="3396498519818009134">"Радня"</string>
<string name="relationTypeSister" msgid="3721676005094140671">"Сястра"</string>
<string name="relationTypeSpouse" msgid="6916682664436031703">"Муж/жонка"</string>
<string name="sipAddressTypeCustom" msgid="6283889809842649336">"Карыстальніцкі"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 02dd4f2bfe3c..32495371ad01 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -970,7 +970,7 @@
<string name="save_password_remember" msgid="6490888932657708341">"Zapamti"</string>
<string name="save_password_never" msgid="6776808375903410659">"Nikad"</string>
<string name="open_permission_deny" msgid="5136793905306987251">"Nemate odobrenje za otvaranje ove stranice."</string>
- <string name="text_copied" msgid="2531420577879738860">"Tekst kopiran u međuspremnik."</string>
+ <string name="text_copied" msgid="2531420577879738860">"Tekst kopiran u međumemoriju."</string>
<string name="copied" msgid="4675902854553014676">"Kopirano"</string>
<string name="more_item_label" msgid="7419249600215749115">"Više"</string>
<string name="prepend_shortcut_label" msgid="1743716737502867951">"Meni+"</string>
@@ -1280,7 +1280,7 @@
<string name="network_switch_type_name_unknown" msgid="3665696841646851068">"nepoznata vrsta mreže"</string>
<string name="accept" msgid="5447154347815825107">"Prihvati"</string>
<string name="decline" msgid="6490507610282145874">"Odbijte"</string>
- <string name="select_character" msgid="3352797107930786979">"Umetni karakter"</string>
+ <string name="select_character" msgid="3352797107930786979">"Umetni znak"</string>
<string name="sms_control_title" msgid="4748684259903148341">"Slanje SMS poruka"</string>
<string name="sms_control_message" msgid="6574313876316388239">"&lt;b&gt;<xliff:g id="APP_NAME">%1$s</xliff:g>&lt;/b&gt; šalje veliki broj SMS poruka. Da li želite dozvoliti ovoj aplikaciji da nastavi slanje poruka?"</string>
<string name="sms_control_yes" msgid="4858845109269524622">"Dozvoli"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 6529de8af786..1c882acd40ee 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1221,7 +1221,7 @@
<string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"S\'ha establert el so de silenci"</string>
<string name="volume_call" msgid="7625321655265747433">"Volum en trucada"</string>
<string name="volume_bluetooth_call" msgid="2930204618610115061">"Volum en trucada per Bluetooth"</string>
- <string name="volume_alarm" msgid="4486241060751798448">"Volum de l\'alarma"</string>
+ <string name="volume_alarm" msgid="4486241060751798448">"Volum d\'alarma"</string>
<string name="volume_notification" msgid="6864412249031660057">"Volum de notificacions"</string>
<string name="volume_unknown" msgid="4041914008166576293">"Volum"</string>
<string name="volume_icon_description_bluetooth" msgid="7540388479345558400">"Volum del Bluetooth"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 7e5d6f227de0..e16c8c28c270 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1258,7 +1258,7 @@
<string name="volume_ringtone" msgid="134784084629229029">"Hlasitost vyzvánění"</string>
<string name="volume_music" msgid="7727274216734955095">"Hlasitost médií"</string>
<string name="volume_music_hint_playing_through_bluetooth" msgid="2614142915948898228">"Přehrávání pomocí rozhraní Bluetooth"</string>
- <string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"Je nastaven tichý vyzváněcí tón"</string>
+ <string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"Je nastaven tichý vyzvánění"</string>
<string name="volume_call" msgid="7625321655265747433">"Hlasitost hovoru"</string>
<string name="volume_bluetooth_call" msgid="2930204618610115061">"Hlasitost příchozích hovorů při připojení Bluetooth"</string>
<string name="volume_alarm" msgid="4486241060751798448">"Hlasitost budíku"</string>
@@ -1269,10 +1269,10 @@
<string name="volume_icon_description_incall" msgid="4491255105381227919">"Hlasitost hovoru"</string>
<string name="volume_icon_description_media" msgid="4997633254078171233">"Hlasitost médií"</string>
<string name="volume_icon_description_notification" msgid="579091344110747279">"Hlasitost oznámení"</string>
- <string name="ringtone_default" msgid="9118299121288174597">"Výchozí vyzváněcí tón"</string>
+ <string name="ringtone_default" msgid="9118299121288174597">"Výchozí vyzvánění"</string>
<string name="ringtone_default_with_actual" msgid="2709686194556159773">"Výchozí (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
<string name="ringtone_silent" msgid="397111123930141876">"Žádný"</string>
- <string name="ringtone_picker_title" msgid="667342618626068253">"Vyzváněcí tóny"</string>
+ <string name="ringtone_picker_title" msgid="667342618626068253">"Vyzvánění"</string>
<string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"Zvuky budíku"</string>
<string name="ringtone_picker_title_notification" msgid="6387191794719608122">"Zvuky upozornění"</string>
<string name="ringtone_unknown" msgid="5059495249862816475">"Neznámé"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index f428b1da4a9f..09e2ea20cd92 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -654,7 +654,7 @@
<string name="permlab_accessNetworkConditions" msgid="1270732533356286514">"observer netværksforhold"</string>
<string name="permdesc_accessNetworkConditions" msgid="2959269186741956109">"Tillader, at en applikation observerer netværksforhold. Bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_setInputCalibration" msgid="932069700285223434">"skift kalibrering for inputenheden"</string>
- <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"Tillader, at appen ændrer kalibreringsparametrene for berøringsskærmen. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+ <string name="permdesc_setInputCalibration" msgid="2937872391426631726">"Tillader, at appen ændrer kalibreringsparametrene for touchskærmen. Dette bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"få adgang til DRM-certifikater"</string>
<string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"Tillader, at en applikation provisionerer og anvender DRM-certifikater. Dette bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_handoverStatus" msgid="7620438488137057281">"modtag status for Android Beam-overførsler"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index b8c00d049721..1024729b53fe 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -421,7 +421,7 @@
<string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"Esta app puede agregar, quitar o cambiar eventos del calendario en tu teléfono. Puede enviar mensajes que parecen proceder de propietarios del calendario o cambiar eventos sin notificarlos."</string>
<string name="permlab_accessLocationExtraCommands" msgid="5162339812057983988">"acceder a comandos adicionales del proveedor del lugar"</string>
<string name="permdesc_accessLocationExtraCommands" msgid="355369611979907967">"Permite que la aplicación acceda a comandos adicionales del proveedor de ubicación. Esto puede permitirle a la aplicación interferir con el funcionamiento del GPS o de otras fuentes de ubicación."</string>
- <string name="permlab_accessFineLocation" msgid="6426318438195622966">"acceder a la ubicación exacta solo en primer plano"</string>
+ <string name="permlab_accessFineLocation" msgid="6426318438195622966">"acceder a la ubicación precisa solo en primer plano"</string>
<string name="permdesc_accessFineLocation" msgid="6732174080240016335">"Mientras la usas, esta app puede obtener tu ubicación exacta mediante los Servicios de ubicación, siempre y cuando el dispositivo los tenga activados. Es posible que esto aumente el uso de batería."</string>
<string name="permlab_accessCoarseLocation" msgid="1561042925407799741">"acceder a la ubicación aproximada solo en primer plano"</string>
<string name="permdesc_accessCoarseLocation" msgid="778521847873199160">"Mientras la usas, esta app puede obtener tu ubicación aproximada mediante los Servicios de ubicación, siempre y cuando el dispositivo los tenga activados."</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index cd3e6f77db5a..c0ec8e039de7 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -482,8 +482,8 @@
<string name="permdesc_setTimeZone" product="default" msgid="4611828585759488256">"Telefonoaren ordu-zona aldatzeko baimena ematen die aplikazioei."</string>
<string name="permlab_getAccounts" msgid="5304317160463582791">"bilatu gailuko kontuak"</string>
<string name="permdesc_getAccounts" product="tablet" msgid="1784452755887604512">"Tabletak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dauzkazun aplikazioek sortutako kontuak har daitezke barnean."</string>
- <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Android TV gailuak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Kontu horien artean, instalatuta dituzun aplikazioek sortutako kontuak egon litezke."</string>
- <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dituzun aplikazioek sortutako kontuak har daitezke barnean."</string>
+ <string name="permdesc_getAccounts" product="tv" msgid="437604680436540822">"Android TV gailuak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Kontu horien artean, instalatuta dauzkazun aplikazioek sortutako kontuak egon litezke."</string>
+ <string name="permdesc_getAccounts" product="default" msgid="2491273043569751867">"Telefonoak ezagutzen dituen kontuen zerrenda lortzeko baimena ematen die aplikazioei. Instalatuta dauzkazun aplikazioek sortutako kontuak har daitezke barnean."</string>
<string name="permlab_accessNetworkState" msgid="2349126720783633918">"ikusi sareko konexioak"</string>
<string name="permdesc_accessNetworkState" msgid="4394564702881662849">"Sareko konexioei buruzko informazioa ikusteko baimena ematen die aplikazioei; adibidez, zer sare dauden eta zeintzuk dauden konektatuta."</string>
<string name="permlab_createNetworkSockets" msgid="3224420491603590541">"izan sarerako sarbide osoa"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index e5600b0e414d..b7a332efed21 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -849,7 +849,7 @@
<string name="lockscreen_transport_pause_description" msgid="6705284702135372494">"Pausar"</string>
<string name="lockscreen_transport_play_description" msgid="106868788691652733">"Reproducir"</string>
<string name="lockscreen_transport_stop_description" msgid="1449552232598355348">"Deter"</string>
- <string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Rebobinar"</string>
+ <string name="lockscreen_transport_rew_description" msgid="7680106856221622779">"Retroceder"</string>
<string name="lockscreen_transport_ffw_description" msgid="4763794746640196772">"Avance rápido"</string>
<string name="emergency_calls_only" msgid="3057351206678279851">"Só chamadas de emerxencia"</string>
<string name="lockscreen_network_locked_message" msgid="2814046965899249635">"Bloqueada pola rede"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 5ba54d3ab9e2..6726be21ae67 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -1135,7 +1135,7 @@
<string name="whichGiveAccessToApplicationLabel" msgid="7805857277166106236">"ઍક્સેસ આપો"</string>
<string name="whichEditApplication" msgid="6191568491456092812">"આનાથી સંપાદિત કરો"</string>
<string name="whichEditApplicationNamed" msgid="8096494987978521514">"%1$s સાથે સંપાદિત કરો"</string>
- <string name="whichEditApplicationLabel" msgid="1463288652070140285">"સંપાદિત કરો"</string>
+ <string name="whichEditApplicationLabel" msgid="1463288652070140285">"ફેરફાર કરો"</string>
<string name="whichSendApplication" msgid="4143847974460792029">"શેર કરો"</string>
<string name="whichSendApplicationNamed" msgid="4470386782693183461">"%1$s સાથે શેર કરો"</string>
<string name="whichSendApplicationLabel" msgid="7467813004769188515">"શેર કરો"</string>
@@ -1221,7 +1221,7 @@
<string name="volume_music_hint_silent_ringtone_selected" msgid="1514829655029062233">"સાઇલેન્ટ રિંગટોન સેટ કરી"</string>
<string name="volume_call" msgid="7625321655265747433">"ઇન-કૉલ વૉલ્યૂમ"</string>
<string name="volume_bluetooth_call" msgid="2930204618610115061">"બ્લૂટૂથ ઇન-કૉલ વૉલ્યૂમ"</string>
- <string name="volume_alarm" msgid="4486241060751798448">"એલાર્મ વૉલ્યૂમ"</string>
+ <string name="volume_alarm" msgid="4486241060751798448">"અલાર્મ વૉલ્યૂમ"</string>
<string name="volume_notification" msgid="6864412249031660057">"સૂચના વૉલ્યૂમ"</string>
<string name="volume_unknown" msgid="4041914008166576293">"વૉલ્યૂમ"</string>
<string name="volume_icon_description_bluetooth" msgid="7540388479345558400">"બ્લૂટૂથ વૉલ્યૂમ"</string>
@@ -1513,7 +1513,7 @@
<string name="storage_usb_drive" msgid="448030813201444573">"USB ડ્રાઇવ"</string>
<string name="storage_usb_drive_label" msgid="6631740655876540521">"<xliff:g id="MANUFACTURER">%s</xliff:g> USB ડ્રાઇવ"</string>
<string name="storage_usb" msgid="2391213347883616886">"USB સ્ટોરેજ"</string>
- <string name="extract_edit_menu_button" msgid="63954536535863040">"સંપાદિત કરો"</string>
+ <string name="extract_edit_menu_button" msgid="63954536535863040">"ફેરફાર કરો"</string>
<string name="data_usage_warning_title" msgid="9034893717078325845">"ડેટા ચેતવણી"</string>
<string name="data_usage_warning_body" msgid="1669325367188029454">"તમે <xliff:g id="APP">%s</xliff:g> ડેટા વાપર્યો છે"</string>
<string name="data_usage_mobile_limit_title" msgid="3911447354393775241">"મોબાઇલ ડેટાની મર્યાદા આવી ગઈ"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index b66d7cb3136e..34e1db5ef4ce 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -307,7 +307,7 @@
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"hanganyag rögzítése"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Testmozgás"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"hozzáférés a testmozgási adatokhoz"</string>
- <string name="permgrouplab_camera" msgid="9090413408963547706">"Fényképezőgép"</string>
+ <string name="permgrouplab_camera" msgid="9090413408963547706">"Kamera"</string>
<string name="permgroupdesc_camera" msgid="7585150538459320326">"fotók és videók készítése"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"Hívásnaplók"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"hívásnapló olvasása és írása"</string>
@@ -1900,8 +1900,8 @@
<string name="profile_encrypted_message" msgid="1128512616293157802">"A feloldáshoz koppintson rá"</string>
<string name="usb_mtp_launch_notification_title" msgid="774319638256707227">"Csatlakoztatva a(z) <xliff:g id="PRODUCT_NAME">%1$s</xliff:g> eszközhöz"</string>
<string name="usb_mtp_launch_notification_description" msgid="6942535713629852684">"Koppintson ide a fájlok megtekintéséhez"</string>
- <string name="pin_target" msgid="8036028973110156895">"Rögzítés"</string>
- <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> rögzítése"</string>
+ <string name="pin_target" msgid="8036028973110156895">"Kitűzés"</string>
+ <string name="pin_specific_target" msgid="7824671240625957415">"<xliff:g id="LABEL">%1$s</xliff:g> kitűzése"</string>
<string name="unpin_target" msgid="3963318576590204447">"Feloldás"</string>
<string name="unpin_specific_target" msgid="3859828252160908146">"<xliff:g id="LABEL">%1$s</xliff:g> rögzítésének feloldása"</string>
<string name="app_info" msgid="6113278084877079851">"Alkalmazásinformáció"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index b531d02998e4..30b092d92a80 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -1979,7 +1979,7 @@
<string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"Չհաջողվեց վերականգնել դյուրանցումը, քանի որ հավելվածների ստորագրությունները տարբեր են"</string>
<string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"Չհաջողվեց վերականգնել դյուրանցումը"</string>
<string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"Դյուրանցումն անջատված է"</string>
- <string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"ՀԵՌԱՑՆԵԼ"</string>
+ <string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"ԱՊԱՏԵՂԱԴՐԵԼ"</string>
<string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"ԲԱՑԵԼ"</string>
<string name="harmful_app_warning_title" msgid="8794823880881113856">"Հայտնաբերվել է վնասաբեր հավելված"</string>
<string name="slices_permission_request" msgid="3677129866636153406">"<xliff:g id="APP_0">%1$s</xliff:g> հավելվածն ուզում է ցուցադրել հատվածներ <xliff:g id="APP_2">%2$s</xliff:g> հավելվածից"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index cac9168e2a2c..7a36d13fbe9d 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1231,7 +1231,7 @@
<string name="volume_icon_description_notification" msgid="579091344110747279">"Volume pemberitahuan"</string>
<string name="ringtone_default" msgid="9118299121288174597">"Nada dering default"</string>
<string name="ringtone_default_with_actual" msgid="2709686194556159773">"Default (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
- <string name="ringtone_silent" msgid="397111123930141876">"Tidak Ada"</string>
+ <string name="ringtone_silent" msgid="397111123930141876">"Tidak ada"</string>
<string name="ringtone_picker_title" msgid="667342618626068253">"Nada dering"</string>
<string name="ringtone_picker_title_alarm" msgid="7438934548339024767">"Suara alarm"</string>
<string name="ringtone_picker_title_notification" msgid="6387191794719608122">"Suara notifikasi"</string>
@@ -2034,7 +2034,7 @@
<string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Aplikasi ini tidak diberi izin merekam, tetapi dapat merekam audio melalui perangkat USB ini."</string>
<string name="accessibility_system_action_home_label" msgid="3234748160850301870">"Beranda"</string>
<string name="accessibility_system_action_back_label" msgid="4205361367345537608">"Kembali"</string>
- <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"Aplikasi yang Baru Dipakai"</string>
+ <string name="accessibility_system_action_recents_label" msgid="4782875610281649728">"Aplikasi Terbaru"</string>
<string name="accessibility_system_action_notifications_label" msgid="6083767351772162010">"Notifikasi"</string>
<string name="accessibility_system_action_quick_settings_label" msgid="4583900123506773783">"Setelan Cepat"</string>
<string name="accessibility_system_action_power_dialog_label" msgid="8095341821683910781">"Dialog Daya"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 692547b2d581..61754b25f4f4 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -1792,7 +1792,7 @@
<string name="package_updated_device_owner" msgid="7560272363805506941">"Әкімші жаңартқан"</string>
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Әкімші жойған"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"Жарайды"</string>
- <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Батарея жұмысының ұзақтығын арттыру үшін Battery Saver:\n\n•қараңғы тақырыпты іске қосады;\n•фондық әрекеттерді, кейбір көрнекі әсерлерді және \"Ok Google\" сияқты басқа да функцияларды өшіреді не шектейді.\n\n"<annotation id="url">"Толығырақ"</annotation></string>
+ <string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Батарея жұмысының ұзақтығын арттыру үшін Батареяны үнемдеу режимі:\n\n•қараңғы тақырыпты іске қосады;\n•фондық әрекеттерді, кейбір көрнекі әсерлерді және \"Ok Google\" сияқты басқа да функцияларды өшіреді не шектейді.\n\n"<annotation id="url">"Толығырақ"</annotation></string>
<string name="battery_saver_description" msgid="6794188153647295212">"Батарея ұзағырақ жұмыс істеуі үшін, Battery Saver:\n\n• қараңғы тақырыпты қосады;\n•фондық жұмысты, кейбір визуалды әсерлерді және \"Ok Google\" сияқты басқа функцияларды өшіреді не шектейді."</string>
<string name="data_saver_description" msgid="4995164271550590517">"Дерек шығынын азайту үшін Data Saver функциясы кейбір қолданбаларға деректерді фондық режимде жіберуге және алуға жол бермейді. Ашық тұрған қолданба деректерді пайдаланады, бірақ шектеулі шамада (мысалы, кескіндер оларды түрткенге дейін көрсетілмейді)."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Data Saver функциясын қосу керек пе?"</string>
@@ -1912,7 +1912,7 @@
<string name="conference_call" msgid="5731633152336490471">"Конференциялық қоңырау"</string>
<string name="tooltip_popup_title" msgid="7863719020269945722">"Қалқыма сөзкөмек"</string>
<string name="app_category_game" msgid="4534216074910244790">"Ойындар"</string>
- <string name="app_category_audio" msgid="8296029904794676222">"Музыка және аудиомазмұн"</string>
+ <string name="app_category_audio" msgid="8296029904794676222">"Музыка және аудио"</string>
<string name="app_category_video" msgid="2590183854839565814">"Фильм және бейне"</string>
<string name="app_category_image" msgid="7307840291864213007">"Суреттер және кескіндер"</string>
<string name="app_category_social" msgid="2278269325488344054">"Әлеуметтік қолданба мен байланыс"</string>
@@ -2000,7 +2000,7 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"Режим туралы хабарландыру"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"Батарея заряды азаюы мүмкін"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"Батарея ұзаққа жетуі үшін, Battery Saver іске қосылды"</string>
- <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Battery Saver"</string>
+ <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"Батареяны үнемдеу режимі"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"Battery Saver өшірілді"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"Телефонның заряды жеткілікті. Функцияларға енді шектеу қойылмайды."</string>
<string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"Планшеттің заряды жеткілікті. Функцияларға енді шектеу қойылмайды."</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index b939c1ac21ea..738e984aed49 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -2000,7 +2000,7 @@
<string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ការ​ជូនដំណឹង​ព័ត៌មាន​របស់​មុខងារ​ទម្លាប់"</string>
<string name="dynamic_mode_notification_title" msgid="9205715501274608016">"ថ្ម​អាច​នឹង​អស់ មុនពេល​សាកថ្មធម្មតា"</string>
<string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"បាន​បើក​ដំណើរការកម្មវិធី​សន្សំ​ថ្ម ដើម្បីបង្កើនកម្រិត​ថាមពល​​ថ្ម"</string>
- <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"កម្មវិធីសន្សំថ្ម"</string>
+ <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"មុខងារ​សន្សំ​ថ្ម"</string>
<string name="battery_saver_off_notification_title" msgid="7637255960468032515">"កម្មវិធី​សន្សំ​ថ្ម​ត្រូវបានបិទ"</string>
<string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ទូរសព្ទ​មាន​កម្រិតថ្ម​គ្រប់គ្រាន់​។ មុខងារ​ផ្សេងៗ​មិន​ត្រូវបាន​រឹតបន្តឹងទៀត​ទេ។"</string>
<string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"ថេប្លេត​មាន​កម្រិតថ្ម​គ្រប់គ្រាន់​។ មុខងារ​ផ្សេងៗ​មិន​ត្រូវបាន​រឹតបន្តឹងទៀត​ទេ។"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index edc4de685334..1517c17d9615 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -1317,7 +1317,7 @@
<string name="console_running_notification_title" msgid="6087888939261635904">"Сериялык консоль иштетилди"</string>
<string name="console_running_notification_message" msgid="7892751888125174039">"Майнаптуулугуна таасири тиет. Аны өчүрүү үчүн операциялык тутумду жүктөгүчтү текшериңиз."</string>
<string name="usb_contaminant_detected_title" msgid="4359048603069159678">"USB портунда суюктук же урандылар бар"</string>
- <string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB порт автоматтык түрдө өчүрүлдү. Кененирээк маалымат алуу үчүн, таптап коюңуз."</string>
+ <string name="usb_contaminant_detected_message" msgid="7346100585390795743">"USB порт автоматтык түрдө өчтү. Кененирээк маалымат алуу үчүн, таптап коюңуз."</string>
<string name="usb_contaminant_not_detected_title" msgid="2651167729563264053">"USB портун колдонууга болот"</string>
<string name="usb_contaminant_not_detected_message" msgid="892863190942660462">"Телефон суюктук менен урандыларды аныктаган жок."</string>
<string name="taking_remote_bugreport_notification_title" msgid="1582531382166919850">"Мүчүлүштүк тууралуу кабар алынууда…"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 6af5d5ee87ca..3833605fa78b 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1117,7 +1117,7 @@
<string name="yes" msgid="9069828999585032361">"ОК"</string>
<string name="no" msgid="5122037903299899715">"Цуцлах"</string>
<string name="dialog_alert_title" msgid="651856561974090712">"Анхаар"</string>
- <string name="loading" msgid="3138021523725055037">"Ачааллаж байна..."</string>
+ <string name="loading" msgid="3138021523725055037">"Ачаалж байна..."</string>
<string name="capital_on" msgid="2770685323900821829">"Идэвхтэй"</string>
<string name="capital_off" msgid="7443704171014626777">"Идэвхгүй"</string>
<string name="checked" msgid="9179896827054513119">"тэмдэглэсэн"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index 317092aaedad..520f97321e8c 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -302,13 +302,13 @@
<string name="permgrouplab_sms" msgid="795737735126084874">"SMS"</string>
<string name="permgroupdesc_sms" msgid="5726462398070064542">"SMS सन्देशहरू पठाउनुहोस् र हेर्नुहोस्"</string>
<string name="permgrouplab_storage" msgid="1938416135375282333">"फाइल र मिडिया"</string>
- <string name="permgroupdesc_storage" msgid="6351503740613026600">"तपाईंको यन्त्रमा तस्बिर, मिडिया, र फाइलहरूमाथि पहुँच गर्नुहोस्"</string>
+ <string name="permgroupdesc_storage" msgid="6351503740613026600">"तपाईंको यन्त्रमा फोटो, मिडिया, र फाइलहरूमाथि पहुँच गर्नुहोस्"</string>
<string name="permgrouplab_microphone" msgid="2480597427667420076">"माइक्रोफोन"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"अडियो रेकर्ड गर्नुहोस्"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"शारीरिक क्रियाकलाप"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"आफ्नो शारीरिक क्रियाकलापको डेटामाथि पहुँच राख्नु"</string>
<string name="permgrouplab_camera" msgid="9090413408963547706">"क्यामेरा"</string>
- <string name="permgroupdesc_camera" msgid="7585150538459320326">"तस्बिर खिच्नुका साथै भिडियो रेकर्ड गर्नुहोस्"</string>
+ <string name="permgroupdesc_camera" msgid="7585150538459320326">"फोटो खिच्नुका साथै भिडियो रेकर्ड गर्नुहोस्"</string>
<string name="permgrouplab_calllog" msgid="7926834372073550288">"कलका लगहरू"</string>
<string name="permgroupdesc_calllog" msgid="2026996642917801803">"फोन कलको लग पढ्नुहोस् र लेख्नुहोस्"</string>
<string name="permgrouplab_phone" msgid="570318944091926620">"फोन"</string>
@@ -435,10 +435,10 @@
<string name="permdesc_sim_communication" msgid="4179799296415957960">"SIM लाई आदेश पठाउन एपलाई अनुमति दिन्छ। यो निकै खतरनाक हुन्छ।"</string>
<string name="permlab_activityRecognition" msgid="1782303296053990884">"शारीरिक गतिविधि पहिचान गर्नुहोस्‌"</string>
<string name="permdesc_activityRecognition" msgid="8667484762991357519">"यो अनुप्रयोगले तपाईंको शारीरिक गतिविधिको पहिचान गर्न सक्छ।"</string>
- <string name="permlab_camera" msgid="6320282492904119413">"तस्बिरहरू र भिडियोहरू लिनुहोस्।"</string>
- <string name="permdesc_camera" msgid="1354600178048761499">"यस अनुप्रयोगले जुनसुकै समय क्यामेराको प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ।"</string>
- <string name="permlab_systemCamera" msgid="3642917457796210580">"एप वा सेवालाई तस्बिर र भिडियो खिच्न प्रणालीका क्यामेराहरूमाथि पहुँच राख्न दिनुहोस्"</string>
- <string name="permdesc_systemCamera" msgid="5938360914419175986">"प्रणालीको यस विशेषाधिकार प्राप्त अनुप्रयोगले जुनसुकै बेला प्रणालीको क्यामेरा प्रयोग गरी तस्बिर खिच्न र भिडियो रेकर्ड गर्न सक्छ। अनुप्रयोगसँग पनि android.permission.CAMERA प्रयोग गर्ने अनुमति हुनु पर्छ"</string>
+ <string name="permlab_camera" msgid="6320282492904119413">"फोटोहरू र भिडियोहरू लिनुहोस्।"</string>
+ <string name="permdesc_camera" msgid="1354600178048761499">"यस अनुप्रयोगले जुनसुकै समय क्यामेराको प्रयोग गरी फोटो खिच्न र भिडियो रेकर्ड गर्न सक्छ।"</string>
+ <string name="permlab_systemCamera" msgid="3642917457796210580">"एप वा सेवालाई फोटो र भिडियो खिच्न प्रणालीका क्यामेराहरूमाथि पहुँच राख्न दिनुहोस्"</string>
+ <string name="permdesc_systemCamera" msgid="5938360914419175986">"प्रणालीको यस विशेषाधिकार प्राप्त अनुप्रयोगले जुनसुकै बेला प्रणालीको क्यामेरा प्रयोग गरी फोटो खिच्न र भिडियो रेकर्ड गर्न सक्छ। अनुप्रयोगसँग पनि android.permission.CAMERA प्रयोग गर्ने अनुमति हुनु पर्छ"</string>
<string name="permlab_cameraOpenCloseListener" msgid="5548732769068109315">"कुनै एप वा सेवालाई खोलिँदै वा बन्द गरिँदै गरेका क्यामेरा यन्त्रहरूका बारेमा कलब्याक प्राप्त गर्ने अनुमति दिनुहोस्।"</string>
<string name="permdesc_cameraOpenCloseListener" msgid="2002636131008772908">"कुनै क्यामेरा यन्त्र खोलिँदा (कुन अनुप्रयोगले खोलेको भन्ने बारेमा) वा बन्द गरिँदा यो अनुप्रयोगले कलब्याक प्राप्त गर्न सक्छ।"</string>
<string name="permlab_vibrate" msgid="8596800035791962017">"कम्पन नियन्त्रण गर्नुहोस्"</string>
@@ -1344,7 +1344,7 @@
<string name="ext_media_new_notification_title" product="automotive" msgid="9085349544984742727">"<xliff:g id="NAME">%s</xliff:g> ले काम गरिरहेको छैन"</string>
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"सेटअप गर्न ट्याप गर्नुहोस्"</string>
<string name="ext_media_new_notification_message" product="automotive" msgid="5140127881613227162">"तपाईंले यो यन्त्र पुनः फर्म्याट गर्नु पर्ने हुन सक्छ। यो यन्त्र हटाउन ट्याप गर्नुहोस्।"</string>
- <string name="ext_media_ready_notification_message" msgid="777258143284919261">"तस्बिरहरू र मिडिया स्थानान्तरणका लागि"</string>
+ <string name="ext_media_ready_notification_message" msgid="777258143284919261">"फोटोहरू र मिडिया स्थानान्तरणका लागि"</string>
<string name="ext_media_unmountable_notification_title" msgid="4895444667278979910">"<xliff:g id="NAME">%s</xliff:g> मा समस्या देखियो"</string>
<string name="ext_media_unmountable_notification_title" product="automotive" msgid="3142723758949023280">"<xliff:g id="NAME">%s</xliff:g> ले काम गरिरहेको छैन"</string>
<string name="ext_media_unmountable_notification_message" msgid="3256290114063126205">"समस्या समाधान गर्न ट्याप गर्नुहोस्"</string>
@@ -1914,7 +1914,7 @@
<string name="app_category_game" msgid="4534216074910244790">"खेलहरू"</string>
<string name="app_category_audio" msgid="8296029904794676222">"सङ्गीत तथा अडियो"</string>
<string name="app_category_video" msgid="2590183854839565814">"चलचित्र तथा भिडियो"</string>
- <string name="app_category_image" msgid="7307840291864213007">"तस्बिर तथा छविहरू"</string>
+ <string name="app_category_image" msgid="7307840291864213007">"फोटो तथा छविहरू"</string>
<string name="app_category_social" msgid="2278269325488344054">"सामाजिक तथा सञ्चार"</string>
<string name="app_category_news" msgid="1172762719574964544">"समाचार तथा पत्रिकाहरू"</string>
<string name="app_category_maps" msgid="6395725487922533156">"नक्सा तथा नेभिगेसन"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 95d5f8f3ab64..bae44fd801ba 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -711,7 +711,7 @@
<item msgid="6216981255272016212">"Aangepast"</item>
</string-array>
<string-array name="emailAddressTypes">
- <item msgid="7786349763648997741">"Thuis"</item>
+ <item msgid="7786349763648997741">"Privé"</item>
<item msgid="435564470865989199">"Werk"</item>
<item msgid="4199433197875490373">"Overig"</item>
<item msgid="3233938986670468328">"Aangepast"</item>
@@ -769,7 +769,7 @@
<string name="eventTypeAnniversary" msgid="4684702412407916888">"Jubileum"</string>
<string name="eventTypeOther" msgid="530671238533887997">"Overig"</string>
<string name="emailTypeCustom" msgid="1809435350482181786">"Aangepast"</string>
- <string name="emailTypeHome" msgid="1597116303154775999">"Thuis"</string>
+ <string name="emailTypeHome" msgid="1597116303154775999">"Privé"</string>
<string name="emailTypeWork" msgid="2020095414401882111">"Werk"</string>
<string name="emailTypeOther" msgid="5131130857030897465">"Overig"</string>
<string name="emailTypeMobile" msgid="787155077375364230">"Mobiel"</string>
@@ -931,9 +931,9 @@
<string name="js_dialog_before_unload" msgid="7213364985774778744">"<xliff:g id="MESSAGE">%s</xliff:g>\n\nWeet u zeker dat u deze pagina wilt verlaten?"</string>
<string name="save_password_label" msgid="9161712335355510035">"Bevestigen"</string>
<string name="double_tap_toast" msgid="7065519579174882778">"Tip: dubbeltik om in en uit te zoomen."</string>
- <string name="autofill_this_form" msgid="3187132440451621492">"Autom. aanvullen"</string>
- <string name="setup_autofill" msgid="5431369130866618567">"Autom. aanvullen instellen"</string>
- <string name="autofill_window_title" msgid="4379134104008111961">"Automatisch aanvullen met <xliff:g id="SERVICENAME">%1$s</xliff:g>"</string>
+ <string name="autofill_this_form" msgid="3187132440451621492">"Autom. invullen"</string>
+ <string name="setup_autofill" msgid="5431369130866618567">"Autom. invullen instellen"</string>
+ <string name="autofill_window_title" msgid="4379134104008111961">"Automatisch invullen met <xliff:g id="SERVICENAME">%1$s</xliff:g>"</string>
<string name="autofill_address_name_separator" msgid="8190155636149596125">" "</string>
<string name="autofill_address_summary_name_format" msgid="3402882515222673691">"$1$2$3"</string>
<string name="autofill_address_summary_separator" msgid="760522655085707045">", "</string>
@@ -1101,7 +1101,7 @@
<string name="selectTextMode" msgid="3225108910999318778">"Tekst selecteren"</string>
<string name="undo" msgid="3175318090002654673">"Ongedaan maken"</string>
<string name="redo" msgid="7231448494008532233">"Opnieuw"</string>
- <string name="autofill" msgid="511224882647795296">"Automatisch aanvullen"</string>
+ <string name="autofill" msgid="511224882647795296">"Automatisch invullen"</string>
<string name="textSelectionCABTitle" msgid="5151441579532476940">"Tekstselectie"</string>
<string name="addToDictionary" msgid="8041821113480950096">"Toevoegen aan woordenboek"</string>
<string name="deleteText" msgid="4200807474529938112">"Verwijderen"</string>
@@ -1276,7 +1276,7 @@
<string name="sms_short_code_confirm_never_allow" msgid="2688828813521652079">"Nooit toestaan"</string>
<string name="sim_removed_title" msgid="5387212933992546283">"Simkaart verwijderd"</string>
<string name="sim_removed_message" msgid="9051174064474904617">"Het mobiele netwerk is niet beschikbaar totdat u het apparaat opnieuw start met een geldige simkaart."</string>
- <string name="sim_done_button" msgid="6464250841528410598">"Gereed"</string>
+ <string name="sim_done_button" msgid="6464250841528410598">"Klaar"</string>
<string name="sim_added_title" msgid="7930779986759414595">"Simkaart aangesloten"</string>
<string name="sim_added_message" msgid="6602906609509958680">"Start je apparaat opnieuw voor toegang tot het mobiele netwerk."</string>
<string name="sim_restart_button" msgid="8481803851341190038">"Opnieuw starten"</string>
@@ -1289,7 +1289,7 @@
<string name="time_picker_dialog_title" msgid="9053376764985220821">"Tijd instellen"</string>
<string name="date_picker_dialog_title" msgid="5030520449243071926">"Datum instellen"</string>
<string name="date_time_set" msgid="4603445265164486816">"Instellen"</string>
- <string name="date_time_done" msgid="8363155889402873463">"Gereed"</string>
+ <string name="date_time_done" msgid="8363155889402873463">"Klaar"</string>
<string name="perms_new_perm_prefix" msgid="6984556020395757087"><font size="12" fgcolor="#ff33b5e5">"NIEUW: "</font></string>
<string name="perms_description_app" msgid="2747752389870161996">"Geleverd door <xliff:g id="APP_NAME">%1$s</xliff:g>."</string>
<string name="no_permissions" msgid="5729199278862516390">"Geen rechten nodig"</string>
@@ -1376,7 +1376,7 @@
<string name="ext_media_status_removed" msgid="241223931135751691">"Verwijderd"</string>
<string name="ext_media_status_unmounted" msgid="8145812017295835941">"Uitgeworpen"</string>
<string name="ext_media_status_checking" msgid="159013362442090347">"Controleren…"</string>
- <string name="ext_media_status_mounted" msgid="3459448555811203459">"Gereed"</string>
+ <string name="ext_media_status_mounted" msgid="3459448555811203459">"Klaar"</string>
<string name="ext_media_status_mounted_ro" msgid="1974809199760086956">"Alleen lezen"</string>
<string name="ext_media_status_bad_removal" msgid="508448566481406245">"Onveilig verwijderd"</string>
<string name="ext_media_status_unmountable" msgid="7043574843541087748">"Beschadigd"</string>
@@ -1401,7 +1401,7 @@
<string name="ime_action_search" msgid="4501435960587287668">"Zoeken"</string>
<string name="ime_action_send" msgid="8456843745664334138">"Verzenden"</string>
<string name="ime_action_next" msgid="4169702997635728543">"Volgende"</string>
- <string name="ime_action_done" msgid="6299921014822891569">"Gereed"</string>
+ <string name="ime_action_done" msgid="6299921014822891569">"Klaar"</string>
<string name="ime_action_previous" msgid="6548799326860401611">"Vorige"</string>
<string name="ime_action_default" msgid="8265027027659800121">"Uitvoeren"</string>
<string name="dial_number_using" msgid="6060769078933953531">"Nummer bellen\nmet <xliff:g id="NUMBER">%s</xliff:g>"</string>
@@ -1448,7 +1448,7 @@
<item quantity="other"><xliff:g id="INDEX">%d</xliff:g> van <xliff:g id="TOTAL">%d</xliff:g></item>
<item quantity="one">1 overeenkomst</item>
</plurals>
- <string name="action_mode_done" msgid="2536182504764803222">"Gereed"</string>
+ <string name="action_mode_done" msgid="2536182504764803222">"Klaar"</string>
<string name="progress_erasing" msgid="6891435992721028004">"Gedeelde opslag wissen…"</string>
<string name="share" msgid="4157615043345227321">"Delen"</string>
<string name="find" msgid="5015737188624767706">"Vinden"</string>
@@ -1492,7 +1492,7 @@
<string name="keyboardview_keycode_alt" msgid="8997420058584292385">"Alt"</string>
<string name="keyboardview_keycode_cancel" msgid="2134624484115716975">"Annuleren"</string>
<string name="keyboardview_keycode_delete" msgid="2661117313730098650">"Delete"</string>
- <string name="keyboardview_keycode_done" msgid="2524518019001653851">"Gereed"</string>
+ <string name="keyboardview_keycode_done" msgid="2524518019001653851">"Klaar"</string>
<string name="keyboardview_keycode_mode_change" msgid="2743735349997999020">"Modus wijzigen"</string>
<string name="keyboardview_keycode_shift" msgid="3026509237043975573">"Shift"</string>
<string name="keyboardview_keycode_enter" msgid="168054869339091055">"Enter"</string>
@@ -1645,7 +1645,7 @@
<string name="accessibility_edit_shortcut_menu_volume_title" msgid="1077294237378645981">"Functies kiezen voor gebruik met de sneltoets via de volumeknop"</string>
<string name="accessibility_uncheck_legacy_item_warning" msgid="8047830891064817447">"<xliff:g id="SERVICE_NAME">%s</xliff:g> is uitgeschakeld"</string>
<string name="edit_accessibility_shortcut_menu_button" msgid="8885752738733772935">"Snelkoppelingen bewerken"</string>
- <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Gereed"</string>
+ <string name="done_accessibility_shortcut_menu_button" msgid="3668407723770815708">"Klaar"</string>
<string name="disable_accessibility_shortcut" msgid="5806091378745232383">"Sneltoets uitschakelen"</string>
<string name="leave_accessibility_shortcut_on" msgid="6543362062336990814">"Sneltoets gebruiken"</string>
<string name="color_inversion_feature_name" msgid="326050048927789012">"Kleurinversie"</string>
@@ -1774,7 +1774,7 @@
<string name="immersive_cling_title" msgid="2307034298721541791">"Volledig scherm wordt weergegeven"</string>
<string name="immersive_cling_description" msgid="7092737175345204832">"Swipe omlaag vanaf de bovenkant van het scherm om af te sluiten."</string>
<string name="immersive_cling_positive" msgid="7047498036346489883">"Ik snap het"</string>
- <string name="done_label" msgid="7283767013231718521">"Gereed"</string>
+ <string name="done_label" msgid="7283767013231718521">"Klaar"</string>
<string name="hour_picker_description" msgid="5153757582093524635">"Ronde schuifregelaar voor uren"</string>
<string name="minute_picker_description" msgid="9029797023621927294">"Ronde schuifregelaar voor minuten"</string>
<string name="select_hours" msgid="5982889657313147347">"Uren selecteren"</string>
@@ -1928,13 +1928,13 @@
<string name="time_picker_prompt_label" msgid="303588544656363889">"Typ een tijd"</string>
<string name="time_picker_text_input_mode_description" msgid="4761160667516611576">"Schakel naar de tekstinvoermodus om de tijd in te voeren."</string>
<string name="time_picker_radial_mode_description" msgid="1222342577115016953">"Schakel naar de klokmodus om de tijd in te voeren."</string>
- <string name="autofill_picker_accessibility_title" msgid="4425806874792196599">"Opties voor automatisch aanvullen"</string>
- <string name="autofill_save_accessibility_title" msgid="1523225776218450005">"Opslaan voor Automatisch aanvullen"</string>
+ <string name="autofill_picker_accessibility_title" msgid="4425806874792196599">"Opties voor automatisch invullen"</string>
+ <string name="autofill_save_accessibility_title" msgid="1523225776218450005">"Opslaan voor Automatisch invullen"</string>
<string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"Content kan niet automatisch worden aangevuld"</string>
- <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Geen suggesties van Automatisch aanvullen"</string>
+ <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Geen suggesties van Automatisch invullen"</string>
<plurals name="autofill_picker_some_suggestions" formatted="false" msgid="6651883186966959978">
- <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggesties van Automatisch aanvullen</item>
- <item quantity="one">Eén suggestie van Automatisch aanvullen</item>
+ <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> suggesties van Automatisch invullen</item>
+ <item quantity="one">Eén suggestie van Automatisch invullen</item>
</plurals>
<string name="autofill_save_title" msgid="7719802414283739775">"Opslaan in "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string>
<string name="autofill_save_title_with_type" msgid="3002460014579799605">"<xliff:g id="TYPE">%1$s</xliff:g> opslaan in "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index dc63de6bbc7a..b9d041ec67f6 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -896,7 +896,7 @@
<string name="keyguard_accessibility_unlock_area_collapsed" msgid="4729922043778400434">"ਅਣਲਾਕ ਖੇਤਰ ਨਸ਼ਟ ਕੀਤਾ।"</string>
<string name="keyguard_accessibility_widget" msgid="6776892679715699875">"<xliff:g id="WIDGET_INDEX">%1$s</xliff:g> ਵਿਜੇਟ।"</string>
<string name="keyguard_accessibility_user_selector" msgid="1466067610235696600">"ਉਪਭੋਗਤਾ ਚੋਣਕਾਰ"</string>
- <string name="keyguard_accessibility_status" msgid="6792745049712397237">"ਅਵਸਥਾ"</string>
+ <string name="keyguard_accessibility_status" msgid="6792745049712397237">"ਸਥਿਤੀ"</string>
<string name="keyguard_accessibility_camera" msgid="7862557559464986528">"ਕੈਮਰਾ"</string>
<string name="keygaurd_accessibility_media_controls" msgid="2267379779900620614">"ਮੀਡੀਆ ਨਿਯੰਤਰਣ"</string>
<string name="keyguard_accessibility_widget_reorder_start" msgid="7066213328912939191">"ਵਿਜੇਟ ਨੂੰ ਪੁਨਰ ਤਰਤੀਬ ਦੇਣਾ ਸ਼ੁਰੂ ਹੋਇਆ।"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 30d3afead0b6..35b5b3a88782 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -241,7 +241,7 @@
<string name="global_action_power_off" msgid="4404936470711393203">"Искључи"</string>
<string name="global_action_power_options" msgid="1185286119330160073">"Напајање"</string>
<string name="global_action_restart" msgid="4678451019561687074">"Рестартуј"</string>
- <string name="global_action_emergency" msgid="1387617624177105088">"Хитни позив"</string>
+ <string name="global_action_emergency" msgid="1387617624177105088">"Хитан позив"</string>
<string name="global_action_bug_report" msgid="5127867163044170003">"Извештај о грешци"</string>
<string name="global_action_logout" msgid="6093581310002476511">"Заврши сесију"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"Снимак екрана"</string>
@@ -832,7 +832,7 @@
<string name="lockscreen_instructions_when_pattern_enabled" msgid="7982445492532123308">"Притисните „Мени“ да бисте откључали телефон или упутите хитан позив."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="7434061749374801753">"Притисните „Мени“ за откључавање."</string>
<string name="lockscreen_pattern_instructions" msgid="3169991838169244941">"Унесите шаблон за откључавање"</string>
- <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Хитни позив"</string>
+ <string name="lockscreen_emergency_call" msgid="7549683825868928636">"Хитан позив"</string>
<string name="lockscreen_return_to_call" msgid="3156883574692006382">"Назад на позив"</string>
<string name="lockscreen_pattern_correct" msgid="8050630103651508582">"Тачно!"</string>
<string name="lockscreen_pattern_wrong" msgid="2940138714468358458">"Пробајте поново"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index fe647cb70d4c..279c619c65fc 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -1829,7 +1829,7 @@
<item quantity="other">I %d tim</item>
<item quantity="one">I en 1 tim</item>
</plurals>
- <string name="zen_mode_until" msgid="2250286190237669079">"Till kl. <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
+ <string name="zen_mode_until" msgid="2250286190237669079">"Till <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
<string name="zen_mode_alarm" msgid="7046911727540499275">"Till <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (nästa alarm)"</string>
<string name="zen_mode_forever" msgid="740585666364912448">"Tills du stänger av"</string>
<string name="zen_mode_forever_dnd" msgid="3423201955704180067">"Tills du inaktiverar Stör ej"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 8276905e2ef0..e168ae44a2d0 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -303,7 +303,7 @@
<string name="permgroupdesc_sms" msgid="5726462398070064542">"itume na iangalie SMS"</string>
<string name="permgrouplab_storage" msgid="1938416135375282333">"Faili na maudhui"</string>
<string name="permgroupdesc_storage" msgid="6351503740613026600">"ifikie picha, maudhui na faili kwenye kifaa chako"</string>
- <string name="permgrouplab_microphone" msgid="2480597427667420076">"Kipokea sauti"</string>
+ <string name="permgrouplab_microphone" msgid="2480597427667420076">"Maikrofoni"</string>
<string name="permgroupdesc_microphone" msgid="1047786732792487722">"irekodi sauti"</string>
<string name="permgrouplab_activityRecognition" msgid="3324466667921775766">"Shughuli za kimwili"</string>
<string name="permgroupdesc_activityRecognition" msgid="4725624819457670704">"ifikie shughuli zako za kimwili"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index 173a8ac900f1..05e00f2a2b6f 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -1793,7 +1793,7 @@
<string name="package_deleted_device_owner" msgid="2292335928930293023">"Administrator tomonidan o‘chirilgan"</string>
<string name="confirm_battery_saver" msgid="5247976246208245754">"OK"</string>
<string name="battery_saver_description_with_learn_more" msgid="4424488535318105801">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Hey Google” kabi boshqa funksiyalarni faolsizlantiradi\n\n"<annotation id="url">"Batafsil"</annotation></string>
- <string name="battery_saver_description" msgid="6794188153647295212">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Hey Google” kabi boshqa funksiyalarni faolsizlantiradi"</string>
+ <string name="battery_saver_description" msgid="6794188153647295212">"Batareya quvvatini uzaytirish uchun Quvvat tejash funksiyasi:\n\n• Tungi mavzuni yoqadi\n• Fondagi harakatlar, vizual effektlar va “Ok Google” kabi boshqa funksiyalarni faolsizlantiradi"</string>
<string name="data_saver_description" msgid="4995164271550590517">"Trafik tejash rejimida ayrim ilovalar uchun orqa fonda internetdan foydalanish imkoniyati cheklanadi. Siz ishlatayotgan ilova zaruratga qarab internet-trafik sarflashi mumkin, biroq cheklangan miqdorda. Masalan, rasmlar ustiga bosmaguningizcha ular yuklanmaydi."</string>
<string name="data_saver_enable_title" msgid="7080620065745260137">"Trafik tejash yoqilsinmi?"</string>
<string name="data_saver_enable_button" msgid="4399405762586419726">"Yoqish"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index a1723c0716de..186af6ea5a3a 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2781,6 +2781,7 @@
<item>power</item>
<item>restart</item>
<item>logout</item>
+ <item>screenshot</item>
<item>bugreport</item>
</string-array>
@@ -3484,6 +3485,7 @@
mode -->
<string-array translatable="false" name="config_priorityOnlyDndExemptPackages">
<item>com.android.dialer</item>
+ <item>com.android.server.telecom</item>
<item>com.android.systemui</item>
<item>android</item>
</string-array>
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index 5c2841aff1d8..7597e8732153 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -129,6 +129,7 @@
<!-- virtual display test permissions -->
<uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
<uses-permission android:name="android.permission.CAPTURE_SECURE_VIDEO_OUTPUT" />
+ <uses-permission android:name="android.permission.ADD_TRUSTED_DISPLAY" />
<!-- color extraction test permissions -->
<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
diff --git a/core/tests/coretests/src/android/content/ContextTest.java b/core/tests/coretests/src/android/content/ContextTest.java
index 777f4a3e03a8..de81ff4d0ca5 100644
--- a/core/tests/coretests/src/android/content/ContextTest.java
+++ b/core/tests/coretests/src/android/content/ContextTest.java
@@ -19,6 +19,7 @@ package android.content;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static com.google.common.truth.Truth.assertThat;
@@ -188,19 +189,38 @@ public class ContextTest {
assertFalse(wrapper.isUiContext());
- wrapper = new ContextWrapper(new TestUiContext());
+ wrapper = new ContextWrapper(getUiContext());
assertTrue(wrapper.isUiContext());
}
- private static class TestUiContext extends ContextWrapper {
- TestUiContext() {
- super(null /* base */);
- }
+ @Test
+ public void testIsUiContext_UiContextDerivedContext() {
+ final Context uiContext = getUiContext();
+ Context context = uiContext.createAttributionContext(null /* attributionTag */);
- @Override
- public boolean isUiContext() {
- return true;
- }
+ assertTrue(context.isUiContext());
+
+ context = uiContext.createConfigurationContext(new Configuration());
+
+ assertTrue(context.isUiContext());
+ }
+
+ @Test
+ public void testIsUiContext_UiContextDerivedDisplayContext() {
+ final Context uiContext = getUiContext();
+ final Display secondaryDisplay =
+ getSecondaryDisplay(uiContext.getSystemService(DisplayManager.class));
+ final Context context = uiContext.createDisplayContext(secondaryDisplay);
+
+ assertFalse(context.isUiContext());
+ }
+
+ private Context getUiContext() {
+ final Context appContext = ApplicationProvider.getApplicationContext();
+ final DisplayManager displayManager = appContext.getSystemService(DisplayManager.class);
+ final Display display = displayManager.getDisplay(DEFAULT_DISPLAY);
+ return appContext.createDisplayContext(display)
+ .createWindowContext(TYPE_APPLICATION_OVERLAY, null /* options */);
}
}
diff --git a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
index daf613976358..0f6284d22d10 100644
--- a/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
+++ b/core/tests/coretests/src/android/hardware/display/VirtualDisplayTest.java
@@ -247,6 +247,25 @@ public class VirtualDisplayTest extends AndroidTestCase {
assertDisplayUnregistered(display);
}
+ /**
+ * Ensures that an application can create a trusted virtual display with the permission
+ * {@code ADD_TRUSTED_DISPLAY}.
+ */
+ public void testTrustedVirtualDisplay() throws Exception {
+ VirtualDisplay virtualDisplay = mDisplayManager.createVirtualDisplay(NAME,
+ WIDTH, HEIGHT, DENSITY, mSurface,
+ DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED);
+ assertNotNull("virtual display must not be null", virtualDisplay);
+
+ Display display = virtualDisplay.getDisplay();
+ try {
+ assertDisplayRegistered(display, Display.FLAG_PRIVATE | Display.FLAG_TRUSTED);
+ } finally {
+ virtualDisplay.release();
+ }
+ assertDisplayUnregistered(display);
+ }
+
private void assertDisplayRegistered(Display display, int flags) {
assertNotNull("display object must not be null", display);
assertTrue("display must be valid", display.isValid());
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index c7d835ca7c7e..576cd78606d7 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -124,6 +124,24 @@ public class InsetsStateTest {
}
@Test
+ public void testCalculateInsets_extraNavRightClimateTop() throws Exception {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(ITYPE_CLIMATE_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_CLIMATE_BAR).setVisible(true);
+ mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
+ mState.getSource(ITYPE_EXTRA_NAVIGATION_BAR).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), null, false,
+ false, DisplayCutout.NO_CUTOUT, 0, 0, 0, null);
+ // ITYPE_CLIMATE_BAR is a type of status bar and ITYPE_EXTRA_NAVIGATION_BAR is a type
+ // of navigation bar.
+ assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.statusBars()));
+ assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.navigationBars()));
+ }
+ }
+
+ @Test
public void testCalculateInsets_imeIgnoredWithoutAdjustResize() {
try (final InsetsModeSession session =
new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
@@ -331,6 +349,8 @@ public class InsetsStateTest {
public void testGetDefaultVisibility() {
assertTrue(InsetsState.getDefaultVisibility(ITYPE_STATUS_BAR));
assertTrue(InsetsState.getDefaultVisibility(ITYPE_NAVIGATION_BAR));
+ assertTrue(InsetsState.getDefaultVisibility(ITYPE_CLIMATE_BAR));
+ assertTrue(InsetsState.getDefaultVisibility(ITYPE_EXTRA_NAVIGATION_BAR));
assertTrue(InsetsState.getDefaultVisibility(ITYPE_CAPTION_BAR));
assertFalse(InsetsState.getDefaultVisibility(ITYPE_IME));
}
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index 5c16772488d0..4cf6715ba0ca 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -24,6 +24,7 @@ import static android.view.View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
import static android.view.View.SYSTEM_UI_FLAG_LOW_PROFILE;
import static android.view.WindowInsetsController.BEHAVIOR_SHOW_BARS_BY_TOUCH;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
+import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
@@ -117,7 +118,15 @@ public class ViewRootImplTest {
final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
- // A window which fits system bars must fit IME, unless its type is toast or system alert.
+ assertEquals(Type.systemBars(), attrs.getFitInsetsTypes());
+ }
+
+ @Test
+ public void adjustLayoutParamsForCompatibility_fitSystemBarsAndIme() {
+ final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(TYPE_APPLICATION);
+ attrs.softInputMode |= SOFT_INPUT_ADJUST_RESIZE;
+ ViewRootImpl.adjustLayoutParamsForCompatibility(attrs);
+
assertEquals(Type.systemBars() | Type.ime(), attrs.getFitInsetsTypes());
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index e08e42aec391..5f34a5eb58a1 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -224,6 +224,7 @@ applications that come with the platform
<permission name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<permission name="android.permission.UPDATE_APP_OPS_STATS"/>
<permission name="android.permission.UPDATE_DEVICE_STATS"/>
+ <permission name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"/>
</privapp-permissions>
<privapp-permissions package="com.android.providers.media.module">
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 2a2aaea035ff..05a9863cb266 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -3039,7 +3039,7 @@ public class LocationManager {
protected GnssRequest merge(@NonNull List<GnssRequest> requests) {
Preconditions.checkArgument(!requests.isEmpty());
for (GnssRequest request : requests) {
- if (request.isFullTracking()) {
+ if (request != null && request.isFullTracking()) {
return request;
}
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 1c0a526f536c..de2a7b2c15e3 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -807,7 +807,8 @@ public class AudioTrack extends PlayerBase
int initResult = native_setup(new WeakReference<AudioTrack>(this), mAttributes,
sampleRate, mChannelMask, mChannelIndexMask, mAudioFormat,
mNativeBufferSizeInBytes, mDataLoadMode, session, 0 /*nativeTrackInJavaObj*/,
- offload, encapsulationMode, tunerConfiguration);
+ offload, encapsulationMode, tunerConfiguration,
+ getCurrentOpPackageName());
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing AudioTrack.");
return; // with mState == STATE_UNINITIALIZED
@@ -893,7 +894,8 @@ public class AudioTrack extends PlayerBase
nativeTrackInJavaObj,
false /*offload*/,
ENCAPSULATION_MODE_NONE,
- null /* tunerConfiguration */);
+ null /* tunerConfiguration */,
+ "" /* opPackagename */);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing AudioTrack.");
return; // with mState == STATE_UNINITIALIZED
@@ -4062,7 +4064,8 @@ public class AudioTrack extends PlayerBase
Object /*AudioAttributes*/ attributes,
int[] sampleRate, int channelMask, int channelIndexMask, int audioFormat,
int buffSizeInBytes, int mode, int[] sessionId, long nativeAudioTrack,
- boolean offload, int encapsulationMode, Object tunerConfiguration);
+ boolean offload, int encapsulationMode, Object tunerConfiguration,
+ @NonNull String opPackageName);
private native final void native_finalize();
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index ed566a50ec58..533f6950fb89 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -68,6 +68,7 @@ import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
+import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.CRC32;
@@ -2079,7 +2080,10 @@ public class ExifInterface {
try {
// Move the original file to temporary file.
if (mFilename != null) {
- tempFile = new File(mFilename + ".tmp");
+ String parent = originalFile.getParent();
+ String name = originalFile.getName();
+ String tempPrefix = UUID.randomUUID().toString() + "_";
+ tempFile = new File(parent, tempPrefix + name);
if (!originalFile.renameTo(tempFile)) {
throw new IOException("Couldn't rename to " + tempFile.getAbsolutePath());
}
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 49e416080041..36ae3ec75a99 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -672,7 +672,8 @@ public class MediaPlayer extends PlayerBase
/* Native setup requires a weak reference to our object.
* It's easier to create it here than in C++.
*/
- native_setup(new WeakReference<MediaPlayer>(this));
+ native_setup(new WeakReference<MediaPlayer>(this),
+ getCurrentOpPackageName());
baseRegisterPlayer();
}
@@ -2378,7 +2379,7 @@ public class MediaPlayer extends PlayerBase
private native final int native_setMetadataFilter(Parcel request);
private static native final void native_init();
- private native final void native_setup(Object mediaplayer_this);
+ private native void native_setup(Object mediaplayerThis, @NonNull String opPackageName);
private native final void native_finalize();
/**
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index ee8f1b3eec77..df5e85edbc30 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -27,6 +27,7 @@ import android.os.Parcelable;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.text.TextUtils;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -622,4 +623,8 @@ public abstract class PlayerBase {
Log.w(className, "See the documentation of " + opName + " for what to use instead with " +
"android.media.AudioAttributes to qualify your playback use case");
}
+
+ protected String getCurrentOpPackageName() {
+ return TextUtils.emptyIfNull(ActivityThread.currentOpPackageName());
+ }
}
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 5cb42a9a96cc..1516c5152054 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -33,6 +33,7 @@
#include <utils/threads.h>
#include "jni.h"
#include <nativehelper/JNIHelp.h>
+#include <nativehelper/ScopedUtfChars.h>
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/android_view_Surface.h"
#include "android_runtime/Log.h"
@@ -944,10 +945,12 @@ android_media_MediaPlayer_native_init(JNIEnv *env)
}
static void
-android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
+android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this,
+ jstring opPackageName)
{
ALOGV("native_setup");
- sp<MediaPlayer> mp = new MediaPlayer();
+ ScopedUtfChars opPackageNameStr(env, opPackageName);
+ sp<MediaPlayer> mp = new MediaPlayer(opPackageNameStr.c_str());
if (mp == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
return;
@@ -1403,7 +1406,7 @@ static const JNINativeMethod gMethods[] = {
{"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
{"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
{"native_init", "()V", (void *)android_media_MediaPlayer_native_init},
- {"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
+ {"native_setup", "(Ljava/lang/Object;Ljava/lang/String;)V",(void *)android_media_MediaPlayer_native_setup},
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
{"getAudioSessionId", "()I", (void *)android_media_MediaPlayer_get_audio_session_id},
{"setAudioSessionId", "(I)V", (void *)android_media_MediaPlayer_set_audio_session_id},
diff --git a/packages/CarSystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/CarSystemUI/res-keyguard/layout/keyguard_password_view.xml
index 8b235e6f246e..d57875f8daba 100644
--- a/packages/CarSystemUI/res-keyguard/layout/keyguard_password_view.xml
+++ b/packages/CarSystemUI/res-keyguard/layout/keyguard_password_view.xml
@@ -53,7 +53,7 @@
android:textColor="?attr/wallpaperTextColor"
android:textAppearance="?android:attr/textAppearanceMedium"
android:imeOptions="flagForceAscii|actionDone"
- android:maxLength="@integer/password_text_view_scale"
+ android:maxLength="@integer/password_max_length"
/>
<TextView
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index 039f2c039ded..24157f9e2038 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -53,6 +53,16 @@
<integer name="config_rightSystemBarZOrder">0</integer>
<integer name="config_bottomSystemBarZOrder">10</integer>
+ <!-- If set to true, the corresponding system bar will be hidden when Keyboard (IME) appears.
+ NOTE: hideBottomSystemBarKeyboard must not be overlaid directly here. To change its value,
+ overlay config_automotiveHideNavBarForKeyboard in framework/base/core/res/res. -->
+ <bool name="config_hideTopSystemBarForKeyboard">false</bool>
+ <bool name="config_hideBottomSystemBarForKeyboard">
+ @*android:bool/config_automotiveHideNavBarForKeyboard
+ </bool>
+ <bool name="config_hideLeftSystemBarForKeyboard">false</bool>
+ <bool name="config_hideRightSystemBarForKeyboard">false</bool>
+
<!-- Disable normal notification rendering; we handle that ourselves -->
<bool name="config_renderNotifications">false</bool>
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
index ccf078b38e0c..b3102e248ab2 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIBinder.java
@@ -21,6 +21,8 @@ import com.android.systemui.bubbles.dagger.BubbleModule;
import com.android.systemui.car.navigationbar.CarNavigationBar;
import com.android.systemui.car.notification.CarNotificationModule;
import com.android.systemui.car.sideloaded.SideLoadedAppController;
+import com.android.systemui.car.statusbar.UnusedStatusBar;
+import com.android.systemui.car.statusbar.UnusedStatusBarModule;
import com.android.systemui.car.voicerecognition.ConnectedDeviceVoiceRecognitionNotifier;
import com.android.systemui.car.volume.VolumeUI;
import com.android.systemui.car.window.OverlayWindowModule;
@@ -34,7 +36,6 @@ import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsModule;
import com.android.systemui.shortcut.ShortcutKeyDispatcher;
import com.android.systemui.stackdivider.Divider;
-import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.notification.InstantAppNotifier;
import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -48,9 +49,9 @@ import dagger.multibindings.ClassKey;
import dagger.multibindings.IntoMap;
/** Binder for car specific {@link SystemUI} modules. */
-@Module(includes = {RecentsModule.class, StatusBarModule.class, NotificationsModule.class,
+@Module(includes = {RecentsModule.class, NotificationsModule.class,
BubbleModule.class, KeyguardModule.class, OverlayWindowModule.class,
- CarNotificationModule.class})
+ CarNotificationModule.class, UnusedStatusBarModule.class})
public abstract class CarSystemUIBinder {
/** Inject into AuthController. */
@Binds
@@ -153,7 +154,7 @@ public abstract class CarSystemUIBinder {
@Binds
@IntoMap
@ClassKey(StatusBar.class)
- public abstract SystemUI bindsStatusBar(StatusBar sysui);
+ public abstract SystemUI bindsStatusBar(UnusedStatusBar sysui);
/** Inject into VolumeUI. */
@Binds
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index cde3699f3084..0e3c7f31886b 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -30,6 +30,7 @@ import com.android.systemui.car.CarDeviceProvisionedControllerImpl;
import com.android.systemui.car.keyguard.CarKeyguardViewController;
import com.android.systemui.car.statusbar.DozeServiceHost;
import com.android.systemui.car.statusbar.DummyNotificationShadeWindowController;
+import com.android.systemui.car.statusbar.UnusedStatusBar;
import com.android.systemui.car.volume.CarVolumeDialogComponent;
import com.android.systemui.dagger.SystemUIRootComponent;
import com.android.systemui.dagger.qualifiers.Background;
@@ -57,6 +58,7 @@ import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.ShadeControllerImpl;
+import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.BatteryControllerImpl;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -175,4 +177,7 @@ public abstract class CarSystemUIModule {
@Binds
abstract DozeHost bindDozeHost(DozeServiceHost dozeServiceHost);
+
+ @Binds
+ abstract StatusBar bindStatusBar(UnusedStatusBar statusBar);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
index 51a7245ea5c6..218c95c2496f 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/keyguard/CarKeyguardViewController.java
@@ -141,7 +141,7 @@ public class CarKeyguardViewController extends OverlayViewController implements
}
@Override
- protected boolean shouldShowNavigationBar() {
+ protected boolean shouldShowNavigationBarInsets() {
return true;
}
@@ -177,7 +177,6 @@ public class CarKeyguardViewController extends OverlayViewController implements
mKeyguardStateController.notifyKeyguardState(mShowing, /* occluded= */ false);
mCarNavigationBarController.showAllKeyguardButtons(/* isSetUp= */ true);
start();
- getOverlayViewGlobalStateController().setWindowFocusable(/* focusable= */ true);
reset(/* hideBouncerWhenShowing= */ false);
notifyKeyguardUpdateMonitor();
}
@@ -192,7 +191,6 @@ public class CarKeyguardViewController extends OverlayViewController implements
mBouncer.hide(/* destroyView= */ true);
mCarNavigationBarController.hideAllKeyguardButtons(/* isSetUp= */ true);
stop();
- getOverlayViewGlobalStateController().setWindowFocusable(/* focusable= */ false);
mKeyguardStateController.notifyKeyguardDoneFading();
mHandler.post(mViewMediatorCallback::keyguardGone);
notifyKeyguardUpdateMonitor();
@@ -237,7 +235,6 @@ public class CarKeyguardViewController extends OverlayViewController implements
public void onCancelClicked() {
if (mBouncer == null) return;
- getOverlayViewGlobalStateController().setWindowFocusable(/* focusable= */ false);
getOverlayViewGlobalStateController().setWindowNeedsInput(/* needsInput= */ false);
mBouncer.hide(/* destroyView= */ true);
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
index 9584850fde7c..b6d251fbfe16 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBar.java
@@ -91,7 +91,11 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
private ActivityManagerWrapper mActivityManagerWrapper;
// If the nav bar should be hidden when the soft keyboard is visible.
- private boolean mHideNavBarForKeyboard;
+ private boolean mHideTopBarForKeyboard;
+ private boolean mHideLeftBarForKeyboard;
+ private boolean mHideRightBarForKeyboard;
+ private boolean mHideBottomBarForKeyboard;
+
private boolean mBottomNavBarVisible;
// Nav bar views.
@@ -160,8 +164,13 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
@Override
public void start() {
// Set initial state.
- mHideNavBarForKeyboard = mResources.getBoolean(
- com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard);
+ mHideTopBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.TOP);
+ mHideBottomBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(
+ SystemBarConfigs.BOTTOM);
+ mHideLeftBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.LEFT);
+ mHideRightBarForKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(
+ SystemBarConfigs.RIGHT);
+
mBottomNavBarVisible = false;
// Connect into the status bar manager service
@@ -407,17 +416,30 @@ public class CarNavigationBar extends SystemUI implements CommandQueue.Callbacks
@Override
public void setImeWindowStatus(int displayId, IBinder token, int vis, int backDisposition,
boolean showImeSwitcher) {
- if (!mHideNavBarForKeyboard) {
- return;
- }
-
if (mContext.getDisplayId() != displayId) {
return;
}
boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
- mCarNavigationBarController.setBottomWindowVisibility(
- isKeyboardVisible ? View.GONE : View.VISIBLE);
+
+ if (mHideTopBarForKeyboard) {
+ mCarNavigationBarController.setTopWindowVisibility(
+ isKeyboardVisible ? View.GONE : View.VISIBLE);
+ }
+
+ if (mHideBottomBarForKeyboard) {
+ mCarNavigationBarController.setBottomWindowVisibility(
+ isKeyboardVisible ? View.GONE : View.VISIBLE);
+ }
+
+ if (mHideLeftBarForKeyboard) {
+ mCarNavigationBarController.setLeftWindowVisibility(
+ isKeyboardVisible ? View.GONE : View.VISIBLE);
+ }
+ if (mHideRightBarForKeyboard) {
+ mCarNavigationBarController.setRightWindowVisibility(
+ isKeyboardVisible ? View.GONE : View.VISIBLE);
+ }
}
@Override
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
index fe26040c5eae..e522d19249e3 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/CarNavigationBarController.java
@@ -79,9 +79,7 @@ public class CarNavigationBarController {
* Hides all system bars.
*/
public void hideBars() {
- if (mTopView != null) {
- mTopView.setVisibility(View.GONE);
- }
+ setTopWindowVisibility(View.GONE);
setBottomWindowVisibility(View.GONE);
setLeftWindowVisibility(View.GONE);
setRightWindowVisibility(View.GONE);
@@ -91,9 +89,7 @@ public class CarNavigationBarController {
* Shows all system bars.
*/
public void showBars() {
- if (mTopView != null) {
- mTopView.setVisibility(View.VISIBLE);
- }
+ setTopWindowVisibility(View.VISIBLE);
setBottomWindowVisibility(View.VISIBLE);
setLeftWindowVisibility(View.VISIBLE);
setRightWindowVisibility(View.VISIBLE);
@@ -135,6 +131,11 @@ public class CarNavigationBarController {
return mShowRight ? mNavigationBarViewFactory.getRightWindow() : null;
}
+ /** Toggles the top nav bar visibility. */
+ public boolean setTopWindowVisibility(@View.Visibility int visibility) {
+ return setWindowVisibility(getTopWindow(), visibility);
+ }
+
/** Toggles the bottom nav bar visibility. */
public boolean setBottomWindowVisibility(@View.Visibility int visibility) {
return setWindowVisibility(getBottomWindow(), visibility);
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java
index 3527bf93682f..694ae6d93b93 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/navigationbar/SystemBarConfigs.java
@@ -29,6 +29,8 @@ import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.R;
+import com.android.systemui.car.notification.BottomNotificationPanelViewMediator;
+import com.android.systemui.car.notification.TopNotificationPanelViewMediator;
import com.android.systemui.dagger.qualifiers.Main;
import java.lang.annotation.ElementType;
@@ -95,6 +97,8 @@ public class SystemBarConfigs {
populateMaps();
readConfigs();
checkEnabledBarsHaveUniqueBarTypes();
+ checkSystemBarEnabledForNotificationPanel();
+ checkHideBottomBarForKeyboardConfigSync();
setInsetPaddingsForOverlappingCorners();
sortSystemBarSidesByZOrder();
}
@@ -119,6 +123,11 @@ public class SystemBarConfigs {
}
}
+ protected boolean getHideForKeyboardBySide(@SystemBarSide int side) {
+ return mSystemBarConfigMap.get(side) != null
+ && mSystemBarConfigMap.get(side).getHideForKeyboard();
+ }
+
protected void insetSystemBar(@SystemBarSide int side, CarNavigationBarView view) {
int[] paddings = mSystemBarConfigMap.get(side).getPaddings();
view.setPadding(paddings[2], paddings[0], paddings[3], paddings[1]);
@@ -164,6 +173,8 @@ public class SystemBarConfigs {
com.android.internal.R.dimen.status_bar_height))
.setBarType(mResources.getInteger(R.integer.config_topSystemBarType))
.setZOrder(mResources.getInteger(R.integer.config_topSystemBarZOrder))
+ .setHideForKeyboard(mResources.getBoolean(
+ R.bool.config_hideTopSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(TOP, topBarConfig);
}
@@ -177,6 +188,8 @@ public class SystemBarConfigs {
.setBarType(mResources.getInteger(R.integer.config_bottomSystemBarType))
.setZOrder(
mResources.getInteger(R.integer.config_bottomSystemBarZOrder))
+ .setHideForKeyboard(mResources.getBoolean(
+ R.bool.config_hideBottomSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(BOTTOM, bottomBarConfig);
}
@@ -189,6 +202,8 @@ public class SystemBarConfigs {
R.dimen.car_left_navigation_bar_width))
.setBarType(mResources.getInteger(R.integer.config_leftSystemBarType))
.setZOrder(mResources.getInteger(R.integer.config_leftSystemBarZOrder))
+ .setHideForKeyboard(mResources.getBoolean(
+ R.bool.config_hideLeftSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(LEFT, leftBarConfig);
}
@@ -201,6 +216,8 @@ public class SystemBarConfigs {
R.dimen.car_right_navigation_bar_width))
.setBarType(mResources.getInteger(R.integer.config_rightSystemBarType))
.setZOrder(mResources.getInteger(R.integer.config_rightSystemBarZOrder))
+ .setHideForKeyboard(mResources.getBoolean(
+ R.bool.config_hideRightSystemBarForKeyboard))
.build();
mSystemBarConfigMap.put(RIGHT, rightBarConfig);
}
@@ -221,6 +238,52 @@ public class SystemBarConfigs {
}
}
+ private void checkSystemBarEnabledForNotificationPanel() throws RuntimeException {
+
+ String notificationPanelMediatorName =
+ mResources.getString(R.string.config_notificationPanelViewMediator);
+ if (notificationPanelMediatorName == null) {
+ return;
+ }
+
+ Class<?> notificationPanelMediatorUsed = null;
+ try {
+ notificationPanelMediatorUsed = Class.forName(notificationPanelMediatorName);
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ }
+
+ if (!mTopNavBarEnabled && TopNotificationPanelViewMediator.class.isAssignableFrom(
+ notificationPanelMediatorUsed)) {
+ throw new RuntimeException(
+ "Top System Bar must be enabled to use " + notificationPanelMediatorName);
+ }
+
+ if (!mBottomNavBarEnabled && BottomNotificationPanelViewMediator.class.isAssignableFrom(
+ notificationPanelMediatorUsed)) {
+ throw new RuntimeException("Bottom System Bar must be enabled to use "
+ + notificationPanelMediatorName);
+ }
+ }
+
+ private void checkHideBottomBarForKeyboardConfigSync() throws RuntimeException {
+ if (mBottomNavBarEnabled) {
+ boolean actual = mResources.getBoolean(R.bool.config_hideBottomSystemBarForKeyboard);
+ boolean expected = mResources.getBoolean(
+ com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard);
+
+ if (actual != expected) {
+ throw new RuntimeException("config_hideBottomSystemBarForKeyboard must not be "
+ + "overlaid directly and should always refer to"
+ + "config_automotiveHideNavBarForKeyboard. However, their values "
+ + "currently do not sync. Set config_hideBottomSystemBarForKeyguard to "
+ + "@*android:bool/config_automotiveHideNavBarForKeyboard. To change its "
+ + "value, overlay config_automotiveHideNavBarForKeyboard in "
+ + "framework/base/core/res/res.");
+ }
+ }
+ }
+
private void setInsetPaddingsForOverlappingCorners() {
setInsetPaddingForOverlappingCorner(TOP, LEFT);
setInsetPaddingForOverlappingCorner(TOP, RIGHT);
@@ -277,7 +340,7 @@ public class SystemBarConfigs {
}
private static boolean isHorizontalBar(@SystemBarSide int side) {
- return side == TOP || side == BOTTOM;
+ return side == TOP || side == BOTTOM;
}
private static boolean isVerticalBar(@SystemBarSide int side) {
@@ -289,14 +352,17 @@ public class SystemBarConfigs {
private final int mBarType;
private final int mGirth;
private final int mZOrder;
+ private final boolean mHideForKeyboard;
private int[] mPaddings = new int[]{0, 0, 0, 0};
- private SystemBarConfig(@SystemBarSide int side, int barType, int girth, int zOrder) {
+ private SystemBarConfig(@SystemBarSide int side, int barType, int girth, int zOrder,
+ boolean hideForKeyboard) {
mSide = side;
mBarType = barType;
mGirth = girth;
mZOrder = zOrder;
+ mHideForKeyboard = hideForKeyboard;
}
private int getSide() {
@@ -315,6 +381,10 @@ public class SystemBarConfigs {
return mZOrder;
}
+ private boolean getHideForKeyboard() {
+ return mHideForKeyboard;
+ }
+
private int[] getPaddings() {
return mPaddings;
}
@@ -352,6 +422,7 @@ public class SystemBarConfigs {
private int mBarType;
private int mGirth;
private int mZOrder;
+ private boolean mHideForKeyboard;
private SystemBarConfigBuilder setSide(@SystemBarSide int side) {
mSide = side;
@@ -373,8 +444,13 @@ public class SystemBarConfigs {
return this;
}
+ private SystemBarConfigBuilder setHideForKeyboard(boolean hide) {
+ mHideForKeyboard = hide;
+ return this;
+ }
+
private SystemBarConfig build() {
- return new SystemBarConfig(mSide, mBarType, mGirth, mZOrder);
+ return new SystemBarConfig(mSide, mBarType, mGirth, mZOrder, mHideForKeyboard);
}
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
index 8d5843635e5f..7cd559a11158 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/notification/NotificationPanelViewController.java
@@ -91,7 +91,6 @@ public class NotificationPanelViewController extends OverlayPanelViewController
private RecyclerView mNotificationList;
private NotificationViewController mNotificationViewController;
- private boolean mIsTracking;
private boolean mNotificationListAtEnd;
private float mFirstTouchDownOnGlassPane;
private boolean mNotificationListAtEndAtTimeOfTouch;
@@ -194,12 +193,12 @@ public class NotificationPanelViewController extends OverlayPanelViewController
}
@Override
- protected boolean shouldShowNavigationBar() {
+ protected boolean shouldShowNavigationBarInsets() {
return true;
}
@Override
- protected boolean shouldShowStatusBar() {
+ protected boolean shouldShowStatusBarInsets() {
return true;
}
@@ -299,14 +298,14 @@ public class NotificationPanelViewController extends OverlayPanelViewController
// The glass pane is used to view touch events before passed to the notification list.
// This allows us to initialize gesture listeners and detect when to close the notifications
glassPane.setOnTouchListener((v, event) -> {
- if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+ if (isClosingAction(event)) {
mNotificationListAtEndAtTimeOfTouch = false;
}
- if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+ if (isOpeningAction(event)) {
mFirstTouchDownOnGlassPane = event.getRawX();
mNotificationListAtEndAtTimeOfTouch = mNotificationListAtEnd;
// Reset the tracker when there is a touch down on the glass pane.
- mIsTracking = false;
+ setIsTracking(false);
// Pass the down event to gesture detector so that it knows where the touch event
// started.
closeGestureDetector.onTouchEvent(event);
@@ -341,22 +340,21 @@ public class NotificationPanelViewController extends OverlayPanelViewController
// If the card is swiping we should not allow the notification shade to close.
// Hence setting mNotificationListAtEndAtTimeOfTouch to false will stop that
- // for us. We are also checking for mIsTracking because while swiping the
+ // for us. We are also checking for isTracking() because while swiping the
// notification shade to close if the user goes a bit horizontal while swiping
// upwards then also this should close.
- if (mIsNotificationCardSwiping && !mIsTracking) {
+ if (mIsNotificationCardSwiping && !isTracking()) {
mNotificationListAtEndAtTimeOfTouch = false;
}
boolean handled = closeGestureDetector.onTouchEvent(event);
- boolean isTracking = mIsTracking;
+ boolean isTracking = isTracking();
Rect rect = getLayout().getClipBounds();
float clippedHeight = 0;
if (rect != null) {
clippedHeight = rect.bottom;
}
- if (!handled && event.getActionMasked() == MotionEvent.ACTION_UP
- && mIsSwipingVerticallyToClose) {
+ if (!handled && isClosingAction(event) && mIsSwipingVerticallyToClose) {
if (getSettleClosePercentage() < getPercentageFromEndingEdge() && isTracking) {
animatePanel(DEFAULT_FLING_VELOCITY, false);
} else if (clippedHeight != getLayout().getHeight() && isTracking) {
@@ -369,7 +367,7 @@ public class NotificationPanelViewController extends OverlayPanelViewController
// Updating the mNotificationListAtEndAtTimeOfTouch state has to be done after
// the event has been passed to the closeGestureDetector above, such that the
// closeGestureDetector sees the up event before the state has changed.
- if (event.getActionMasked() == MotionEvent.ACTION_UP) {
+ if (isClosingAction(event)) {
mNotificationListAtEndAtTimeOfTouch = false;
}
return handled || isTracking;
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBar.java
new file mode 100644
index 000000000000..48334bd6e5c7
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBar.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car.statusbar;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.util.DisplayMetrics;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.InitController;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.PluginDependencyProvider;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.ScreenPinningRequest;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.init.NotificationsController;
+import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.DozeScrimController;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
+import com.android.systemui.statusbar.phone.KeyguardLiftController;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LightsOutNotifController;
+import com.android.systemui.statusbar.phone.LockscreenLockIconController;
+import com.android.systemui.statusbar.phone.LockscreenWallpaper;
+import com.android.systemui.statusbar.phone.NavigationBarView;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
+import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
+import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
+import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.volume.VolumeComponent;
+
+import java.util.Optional;
+import java.util.concurrent.Executor;
+
+import javax.inject.Provider;
+
+import dagger.Lazy;
+
+/** Unused variant of {@link StatusBar} specifically used in the automotive context. */
+public class UnusedStatusBar extends StatusBar {
+
+ public UnusedStatusBar(Context context,
+ NotificationsController notificationsController,
+ LightBarController lightBarController,
+ AutoHideController autoHideController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ StatusBarIconController statusBarIconController,
+ PulseExpansionHandler pulseExpansionHandler,
+ NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+ KeyguardBypassController keyguardBypassController,
+ KeyguardStateController keyguardStateController,
+ HeadsUpManagerPhone headsUpManagerPhone,
+ DynamicPrivacyController dynamicPrivacyController,
+ BypassHeadsUpNotifier bypassHeadsUpNotifier,
+ FalsingManager falsingManager,
+ BroadcastDispatcher broadcastDispatcher,
+ RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+ NotificationGutsManager notificationGutsManager,
+ NotificationLogger notificationLogger,
+ NotificationInterruptStateProvider notificationInterruptStateProvider,
+ NotificationViewHierarchyManager notificationViewHierarchyManager,
+ KeyguardViewMediator keyguardViewMediator,
+ DisplayMetrics displayMetrics,
+ MetricsLogger metricsLogger,
+ Executor uiBgExecutor,
+ NotificationMediaManager notificationMediaManager,
+ NotificationLockscreenUserManager lockScreenUserManager,
+ NotificationRemoteInputManager remoteInputManager,
+ UserSwitcherController userSwitcherController,
+ NetworkController networkController,
+ BatteryController batteryController,
+ SysuiColorExtractor colorExtractor,
+ ScreenLifecycle screenLifecycle,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ SysuiStatusBarStateController statusBarStateController,
+ VibratorHelper vibratorHelper,
+ BubbleController bubbleController,
+ NotificationGroupManager groupManager,
+ VisualStabilityManager visualStabilityManager,
+ DeviceProvisionedController deviceProvisionedController,
+ NavigationBarController navigationBarController,
+ Lazy<AssistManager> assistManagerLazy,
+ ConfigurationController configurationController,
+ NotificationShadeWindowController notificationShadeWindowController,
+ LockscreenLockIconController lockscreenLockIconController,
+ DozeParameters dozeParameters,
+ ScrimController scrimController,
+ KeyguardLiftController keyguardLiftController,
+ Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+ Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+ DozeServiceHost dozeServiceHost,
+ PowerManager powerManager,
+ ScreenPinningRequest screenPinningRequest,
+ DozeScrimController dozeScrimController,
+ VolumeComponent volumeComponent,
+ CommandQueue commandQueue,
+ Optional<Recents> recentsOptional,
+ Provider<StatusBarComponent.Builder> statusBarComponentBuilder,
+ PluginManager pluginManager,
+ Optional<Divider> dividerOptional,
+ LightsOutNotifController lightsOutNotifController,
+ StatusBarNotificationActivityStarter.Builder statusBarNotifActivityStarterBuilder,
+ ShadeController shadeController,
+ SuperStatusBarViewFactory superStatusBarViewFactory,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+ ViewMediatorCallback viewMediatorCallback,
+ InitController initController,
+ DarkIconDispatcher darkIconDispatcher,
+ Handler timeTickHandler,
+ PluginDependencyProvider pluginDependencyProvider,
+ KeyguardDismissUtil keyguardDismissUtil,
+ ExtensionController extensionController,
+ UserInfoControllerImpl userInfoControllerImpl,
+ PhoneStatusBarPolicy phoneStatusBarPolicy,
+ KeyguardIndicationController keyguardIndicationController,
+ DismissCallbackRegistry dismissCallbackRegistry,
+ Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
+ StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
+ super(context, notificationsController, lightBarController, autoHideController,
+ keyguardUpdateMonitor, statusBarIconController, pulseExpansionHandler,
+ notificationWakeUpCoordinator, keyguardBypassController, keyguardStateController,
+ headsUpManagerPhone, dynamicPrivacyController, bypassHeadsUpNotifier,
+ falsingManager,
+ broadcastDispatcher, remoteInputQuickSettingsDisabler, notificationGutsManager,
+ notificationLogger, notificationInterruptStateProvider,
+ notificationViewHierarchyManager, keyguardViewMediator, displayMetrics,
+ metricsLogger,
+ uiBgExecutor, notificationMediaManager, lockScreenUserManager, remoteInputManager,
+ userSwitcherController, networkController, batteryController, colorExtractor,
+ screenLifecycle, wakefulnessLifecycle, statusBarStateController, vibratorHelper,
+ bubbleController, groupManager, visualStabilityManager, deviceProvisionedController,
+ navigationBarController, assistManagerLazy, configurationController,
+ notificationShadeWindowController, lockscreenLockIconController, dozeParameters,
+ scrimController, keyguardLiftController, lockscreenWallpaperLazy,
+ biometricUnlockControllerLazy, dozeServiceHost, powerManager, screenPinningRequest,
+ dozeScrimController, volumeComponent, commandQueue, recentsOptional,
+ statusBarComponentBuilder, pluginManager, dividerOptional, lightsOutNotifController,
+ statusBarNotifActivityStarterBuilder, shadeController, superStatusBarViewFactory,
+ statusBarKeyguardViewManager, viewMediatorCallback, initController,
+ darkIconDispatcher,
+ timeTickHandler, pluginDependencyProvider, keyguardDismissUtil, extensionController,
+ userInfoControllerImpl, phoneStatusBarPolicy, keyguardIndicationController,
+ dismissCallbackRegistry, notificationShadeDepthControllerLazy,
+ statusBarTouchableRegionManager);
+ }
+
+ @Override
+ public void notifyBiometricAuthModeChanged() {
+ // No-op for Automotive devices.
+ }
+
+ @Override
+ public NavigationBarView getNavigationBarView() {
+ // Return null for Automotive devices.
+ return null;
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBarModule.java
new file mode 100644
index 000000000000..2c86e4db3b82
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/car/statusbar/UnusedStatusBarModule.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.car.statusbar;
+
+import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.util.DisplayMetrics;
+
+import androidx.annotation.Nullable;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.InitController;
+import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.bubbles.BubbleController;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.keyguard.DismissCallbackRegistry;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.PluginDependencyProvider;
+import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.ScreenPinningRequest;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.stackdivider.Divider;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.NavigationBarController;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.SuperStatusBarViewFactory;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.VibratorHelper;
+import com.android.systemui.statusbar.dagger.StatusBarDependenciesModule;
+import com.android.systemui.statusbar.notification.DynamicPrivacyController;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.init.NotificationsController;
+import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.row.NotificationRowModule;
+import com.android.systemui.statusbar.phone.AutoHideController;
+import com.android.systemui.statusbar.phone.BiometricUnlockController;
+import com.android.systemui.statusbar.phone.DozeParameters;
+import com.android.systemui.statusbar.phone.DozeScrimController;
+import com.android.systemui.statusbar.phone.DozeServiceHost;
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
+import com.android.systemui.statusbar.phone.KeyguardLiftController;
+import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.statusbar.phone.LightsOutNotifController;
+import com.android.systemui.statusbar.phone.LockscreenLockIconController;
+import com.android.systemui.statusbar.phone.LockscreenWallpaper;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
+import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
+import com.android.systemui.statusbar.phone.ScrimController;
+import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
+import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
+import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
+import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneDependenciesModule;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.volume.VolumeComponent;
+
+import java.util.Optional;
+import java.util.concurrent.Executor;
+
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
+import dagger.Lazy;
+import dagger.Module;
+import dagger.Provides;
+
+/**
+ * Dagger Module providing {@link UnusedStatusBar}.
+ */
+@Module(includes = {StatusBarDependenciesModule.class, StatusBarPhoneDependenciesModule.class,
+ NotificationRowModule.class})
+public interface UnusedStatusBarModule {
+ /**
+ * Provides our instance of StatusBar which is considered optional.
+ */
+ @Provides
+ @Singleton
+ static UnusedStatusBar provideStatusBar(
+ Context context,
+ NotificationsController notificationsController,
+ LightBarController lightBarController,
+ AutoHideController autoHideController,
+ KeyguardUpdateMonitor keyguardUpdateMonitor,
+ StatusBarIconController statusBarIconController,
+ PulseExpansionHandler pulseExpansionHandler,
+ NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+ KeyguardBypassController keyguardBypassController,
+ KeyguardStateController keyguardStateController,
+ HeadsUpManagerPhone headsUpManagerPhone,
+ DynamicPrivacyController dynamicPrivacyController,
+ BypassHeadsUpNotifier bypassHeadsUpNotifier,
+ FalsingManager falsingManager,
+ BroadcastDispatcher broadcastDispatcher,
+ RemoteInputQuickSettingsDisabler remoteInputQuickSettingsDisabler,
+ NotificationGutsManager notificationGutsManager,
+ NotificationLogger notificationLogger,
+ NotificationInterruptStateProvider notificationInterruptStateProvider,
+ NotificationViewHierarchyManager notificationViewHierarchyManager,
+ KeyguardViewMediator keyguardViewMediator,
+ DisplayMetrics displayMetrics,
+ MetricsLogger metricsLogger,
+ @UiBackground Executor uiBgExecutor,
+ NotificationMediaManager notificationMediaManager,
+ NotificationLockscreenUserManager lockScreenUserManager,
+ NotificationRemoteInputManager remoteInputManager,
+ UserSwitcherController userSwitcherController,
+ NetworkController networkController,
+ BatteryController batteryController,
+ SysuiColorExtractor colorExtractor,
+ ScreenLifecycle screenLifecycle,
+ WakefulnessLifecycle wakefulnessLifecycle,
+ SysuiStatusBarStateController statusBarStateController,
+ VibratorHelper vibratorHelper,
+ BubbleController bubbleController,
+ NotificationGroupManager groupManager,
+ VisualStabilityManager visualStabilityManager,
+ DeviceProvisionedController deviceProvisionedController,
+ NavigationBarController navigationBarController,
+ Lazy<AssistManager> assistManagerLazy,
+ ConfigurationController configurationController,
+ NotificationShadeWindowController notificationShadeWindowController,
+ LockscreenLockIconController lockscreenLockIconController,
+ DozeParameters dozeParameters,
+ ScrimController scrimController,
+ @Nullable KeyguardLiftController keyguardLiftController,
+ Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+ Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+ DozeServiceHost dozeServiceHost,
+ PowerManager powerManager,
+ ScreenPinningRequest screenPinningRequest,
+ DozeScrimController dozeScrimController,
+ VolumeComponent volumeComponent,
+ CommandQueue commandQueue,
+ Optional<Recents> recentsOptional,
+ Provider<StatusBarComponent.Builder> statusBarComponentBuilder,
+ PluginManager pluginManager,
+ Optional<Divider> dividerOptional,
+ LightsOutNotifController lightsOutNotifController,
+ StatusBarNotificationActivityStarter.Builder
+ statusBarNotificationActivityStarterBuilder,
+ ShadeController shadeController,
+ SuperStatusBarViewFactory superStatusBarViewFactory,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+ ViewMediatorCallback viewMediatorCallback,
+ InitController initController,
+ DarkIconDispatcher darkIconDispatcher,
+ @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
+ PluginDependencyProvider pluginDependencyProvider,
+ KeyguardDismissUtil keyguardDismissUtil,
+ ExtensionController extensionController,
+ UserInfoControllerImpl userInfoControllerImpl,
+ PhoneStatusBarPolicy phoneStatusBarPolicy,
+ KeyguardIndicationController keyguardIndicationController,
+ Lazy<NotificationShadeDepthController> notificationShadeDepthController,
+ DismissCallbackRegistry dismissCallbackRegistry,
+ StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
+ return new UnusedStatusBar(
+ context,
+ notificationsController,
+ lightBarController,
+ autoHideController,
+ keyguardUpdateMonitor,
+ statusBarIconController,
+ pulseExpansionHandler,
+ notificationWakeUpCoordinator,
+ keyguardBypassController,
+ keyguardStateController,
+ headsUpManagerPhone,
+ dynamicPrivacyController,
+ bypassHeadsUpNotifier,
+ falsingManager,
+ broadcastDispatcher,
+ remoteInputQuickSettingsDisabler,
+ notificationGutsManager,
+ notificationLogger,
+ notificationInterruptStateProvider,
+ notificationViewHierarchyManager,
+ keyguardViewMediator,
+ displayMetrics,
+ metricsLogger,
+ uiBgExecutor,
+ notificationMediaManager,
+ lockScreenUserManager,
+ remoteInputManager,
+ userSwitcherController,
+ networkController,
+ batteryController,
+ colorExtractor,
+ screenLifecycle,
+ wakefulnessLifecycle,
+ statusBarStateController,
+ vibratorHelper,
+ bubbleController,
+ groupManager,
+ visualStabilityManager,
+ deviceProvisionedController,
+ navigationBarController,
+ assistManagerLazy,
+ configurationController,
+ notificationShadeWindowController,
+ lockscreenLockIconController,
+ dozeParameters,
+ scrimController,
+ keyguardLiftController,
+ lockscreenWallpaperLazy,
+ biometricUnlockControllerLazy,
+ dozeServiceHost,
+ powerManager,
+ screenPinningRequest,
+ dozeScrimController,
+ volumeComponent,
+ commandQueue,
+ recentsOptional,
+ statusBarComponentBuilder,
+ pluginManager,
+ dividerOptional,
+ lightsOutNotifController,
+ statusBarNotificationActivityStarterBuilder,
+ shadeController,
+ superStatusBarViewFactory,
+ statusBarKeyguardViewManager,
+ viewMediatorCallback,
+ initController,
+ darkIconDispatcher,
+ timeTickHandler,
+ pluginDependencyProvider,
+ keyguardDismissUtil,
+ extensionController,
+ userInfoControllerImpl,
+ phoneStatusBarPolicy,
+ keyguardIndicationController,
+ dismissCallbackRegistry,
+ notificationShadeDepthController,
+ statusBarTouchableRegionManager);
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java
index 1a8f19e46798..aac4cfbf83c4 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/userswitcher/FullScreenUserSwitcherViewController.java
@@ -78,6 +78,11 @@ public class FullScreenUserSwitcherViewController extends OverlayViewController
}
@Override
+ protected boolean shouldFocusWindow() {
+ return false;
+ }
+
+ @Override
protected void showInternal() {
getLayout().setVisibility(View.VISIBLE);
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
index 45808a8a0b3e..3c9879c671a5 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayPanelViewController.java
@@ -191,6 +191,38 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
}
}
+ /** Checks if a {@link MotionEvent} is an action to open the panel.
+ * @param e {@link MotionEvent} to check.
+ * @return true only if opening action.
+ */
+ protected boolean isOpeningAction(MotionEvent e) {
+ if (mAnimateDirection == POSITIVE_DIRECTION) {
+ return e.getActionMasked() == MotionEvent.ACTION_DOWN;
+ }
+
+ if (mAnimateDirection == NEGATIVE_DIRECTION) {
+ return e.getActionMasked() == MotionEvent.ACTION_UP;
+ }
+
+ return false;
+ }
+
+ /** Checks if a {@link MotionEvent} is an action to close the panel.
+ * @param e {@link MotionEvent} to check.
+ * @return true only if closing action.
+ */
+ protected boolean isClosingAction(MotionEvent e) {
+ if (mAnimateDirection == POSITIVE_DIRECTION) {
+ return e.getActionMasked() == MotionEvent.ACTION_UP;
+ }
+
+ if (mAnimateDirection == NEGATIVE_DIRECTION) {
+ return e.getActionMasked() == MotionEvent.ACTION_DOWN;
+ }
+
+ return false;
+ }
+
/* ***************************************************************************************** *
* Panel Animation
* ***************************************************************************************** */
@@ -206,7 +238,6 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
}
onAnimateCollapsePanel();
- getOverlayViewGlobalStateController().setWindowFocusable(false);
animatePanel(mClosingVelocity, /* isClosing= */ true);
}
@@ -243,8 +274,7 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
* Depending on certain conditions, determines whether to fully expand or collapse the panel.
*/
protected void maybeCompleteAnimation(MotionEvent event) {
- if (event.getActionMasked() == MotionEvent.ACTION_UP
- && isPanelVisible()) {
+ if (isClosingAction(event) && isPanelVisible()) {
if (mSettleClosePercentage < mPercentageFromEndingEdge) {
animatePanel(DEFAULT_FLING_VELOCITY, false);
} else {
@@ -266,14 +296,17 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
float from = getCurrentStartPosition(rect);
if (from != to) {
animate(from, to, velocity, isClosing);
- return;
}
+
+ // If we swipe down the notification panel all the way to the bottom of the screen
+ // (i.e. from == to), then we have finished animating the panel.
+ return;
}
// We will only be here if the shade is being opened programmatically or via button when
// height of the layout was not calculated.
- ViewTreeObserver notificationTreeObserver = getLayout().getViewTreeObserver();
- notificationTreeObserver.addOnGlobalLayoutListener(
+ ViewTreeObserver panelTreeObserver = getLayout().getViewTreeObserver();
+ panelTreeObserver.addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
@@ -381,7 +414,6 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
getOverlayViewGlobalStateController().hideView(/* panelViewController= */ this);
}
getLayout().setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
- getOverlayViewGlobalStateController().setWindowFocusable(visible);
}
/* ***************************************************************************************** *
@@ -476,6 +508,11 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
return mIsTracking;
}
+ /** Sets whether the panel is currently tracking or not. */
+ protected final void setIsTracking(boolean isTracking) {
+ mIsTracking = isTracking;
+ }
+
/** Returns {@code true} if the panel is currently animating. */
protected final boolean isAnimating() {
return mIsAnimating;
@@ -514,7 +551,7 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
}
setPanelVisible(true);
- // clips the view for the notification shade when the user scrolls to open.
+ // clips the view for the panel when the user scrolls to open.
setViewClipBounds((int) event2.getRawY());
// Initially the scroll starts with height being zero. This checks protects from divide
@@ -569,11 +606,11 @@ public abstract class OverlayPanelViewController extends OverlayViewController {
boolean isInClosingDirection = mAnimateDirection * distanceY > 0;
// This check is to figure out if onScroll was called while swiping the card at
- // bottom of the list. At that time we should not allow notification shade to
+ // bottom of the panel. At that time we should not allow panel to
// close. We are also checking for the upwards swipe gesture here because it is
- // possible if a user is closing the notification shade and while swiping starts
+ // possible if a user is closing the panel and while swiping starts
// to open again but does not fling. At that time we should allow the
- // notification shade to close fully or else it would stuck in between.
+ // panel to close fully or else it would stuck in between.
if (Math.abs(getLayout().getHeight() - y)
> SWIPE_DOWN_MIN_DISTANCE && isInClosingDirection) {
setViewClipBounds((int) y);
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java
index 53deb9d9dc5d..8adc1adcc41c 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewController.java
@@ -136,16 +136,18 @@ public class OverlayViewController {
}
/**
- * Returns {@code true} if navigation bar should be displayed over this view.
+ * Returns {@code true} if navigation bar insets should be displayed over this view. Has no
+ * effect if {@link #shouldFocusWindow} returns {@code false}.
*/
- protected boolean shouldShowNavigationBar() {
+ protected boolean shouldShowNavigationBarInsets() {
return false;
}
/**
- * Returns {@code true} if status bar should be displayed over this view.
+ * Returns {@code true} if status bar insets should be displayed over this view. Has no
+ * effect if {@link #shouldFocusWindow} returns {@code false}.
*/
- protected boolean shouldShowStatusBar() {
+ protected boolean shouldShowStatusBarInsets() {
return false;
}
@@ -157,6 +159,15 @@ public class OverlayViewController {
}
/**
+ * Returns {@code true} if the window should be focued when this view is visible. Note that
+ * returning {@code false} here means that {@link #shouldShowStatusBarInsets} and
+ * {@link #shouldShowNavigationBarInsets} will have no effect.
+ */
+ protected boolean shouldFocusWindow() {
+ return true;
+ }
+
+ /**
* Returns the insets types to fit to the sysui overlay window when this
* {@link OverlayViewController} is in the foreground.
*/
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java
index 2494242c24f0..55f0975aeccf 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/OverlayViewGlobalStateController.java
@@ -18,7 +18,6 @@ package com.android.systemui.car.window;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
-import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import android.annotation.Nullable;
import android.util.Log;
@@ -118,6 +117,7 @@ public class OverlayViewGlobalStateController {
updateInternalsWhenShowingView(viewController);
refreshInsetTypesToFit();
+ refreshWindowFocus();
refreshNavigationBarVisibility();
refreshStatusBarVisibility();
@@ -190,6 +190,7 @@ public class OverlayViewGlobalStateController {
mZOrderVisibleSortedMap.remove(mZOrderMap.get(viewController));
refreshHighestZOrderWhenHidingView(viewController);
refreshInsetTypesToFit();
+ refreshWindowFocus();
refreshNavigationBarVisibility();
refreshStatusBarVisibility();
@@ -214,23 +215,37 @@ public class OverlayViewGlobalStateController {
}
private void refreshNavigationBarVisibility() {
- mWindowInsetsController.setSystemBarsBehavior(BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
- if (mZOrderVisibleSortedMap.isEmpty() || mHighestZOrder.shouldShowNavigationBar()) {
+ if (mZOrderVisibleSortedMap.isEmpty()) {
mWindowInsetsController.show(navigationBars());
- } else {
+ return;
+ }
+
+ // Do not hide navigation bar insets if the window is not focusable.
+ if (mHighestZOrder.shouldFocusWindow() && !mHighestZOrder.shouldShowNavigationBarInsets()) {
mWindowInsetsController.hide(navigationBars());
+ } else {
+ mWindowInsetsController.show(navigationBars());
}
}
private void refreshStatusBarVisibility() {
- mWindowInsetsController.setSystemBarsBehavior(BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
- if (mZOrderVisibleSortedMap.isEmpty() || mHighestZOrder.shouldShowStatusBar()) {
+ if (mZOrderVisibleSortedMap.isEmpty()) {
mWindowInsetsController.show(statusBars());
- } else {
+ return;
+ }
+
+ // Do not hide status bar insets if the window is not focusable.
+ if (mHighestZOrder.shouldFocusWindow() && !mHighestZOrder.shouldShowStatusBarInsets()) {
mWindowInsetsController.hide(statusBars());
+ } else {
+ mWindowInsetsController.show(statusBars());
}
}
+ private void refreshWindowFocus() {
+ setWindowFocusable(mHighestZOrder == null ? false : mHighestZOrder.shouldFocusWindow());
+ }
+
private void refreshInsetTypesToFit() {
if (mZOrderVisibleSortedMap.isEmpty()) {
setFitInsetsTypes(statusBars());
diff --git a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java
index 029bd3702afe..c955fab592f3 100644
--- a/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/car/window/SystemUIOverlayWindowController.java
@@ -16,6 +16,7 @@
package com.android.systemui.car.window;
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import android.content.Context;
@@ -104,6 +105,7 @@ public class SystemUIOverlayWindowController implements
mLp.setTitle("SystemUIOverlayWindow");
mLp.packageName = mContext.getPackageName();
mLp.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+ mLp.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
mWindowManager.addView(mBaseLayout, mLp);
mLpChanged.copyFrom(mLp);
@@ -160,6 +162,7 @@ public class SystemUIOverlayWindowController implements
private void updateWindow() {
if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
if (isAttached()) {
+ mLp.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
mWindowManager.updateViewLayout(mBaseLayout, mLp);
}
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java
index a831464e7987..c9ec34fd5f08 100644
--- a/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java
+++ b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java
@@ -32,6 +32,8 @@ import androidx.annotation.VisibleForTesting;
import com.android.systemui.TransactionPool;
import com.android.systemui.dagger.qualifiers.Main;
+import java.util.Objects;
+
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -90,7 +92,7 @@ public class DisplaySystemBarsController extends DisplayImeController {
}
@VisibleForTesting
- class PerDisplay extends IDisplayWindowInsetsController.Stub {
+ class PerDisplay extends DisplayImeController.PerDisplay {
int mDisplayId;
InsetsController mInsetsController;
@@ -98,6 +100,8 @@ public class DisplaySystemBarsController extends DisplayImeController {
String mPackageName;
PerDisplay(int displayId) {
+ super(displayId,
+ mSystemWindows.mDisplayController.getDisplayLayout(displayId).rotation());
mDisplayId = displayId;
mInsetsController = new InsetsController(
new DisplaySystemBarsInsetsControllerHost(mHandler, this));
@@ -105,6 +109,7 @@ public class DisplaySystemBarsController extends DisplayImeController {
@Override
public void insetsChanged(InsetsState insetsState) {
+ super.insetsChanged(insetsState);
if (mInsetsState.equals(insetsState)) {
return;
}
@@ -118,24 +123,33 @@ public class DisplaySystemBarsController extends DisplayImeController {
@Override
public void insetsControlChanged(InsetsState insetsState,
InsetsSourceControl[] activeControls) {
+ super.insetsControlChanged(insetsState, activeControls);
mInsetsController.onControlsChanged(activeControls);
}
@Override
public void hideInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) {
- mInsetsController.hide(types);
+ if ((types & WindowInsets.Type.ime()) == 0) {
+ mInsetsController.hide(types);
+ } else {
+ super.hideInsets(types, fromIme);
+ }
+
}
@Override
public void showInsets(@WindowInsets.Type.InsetsType int types, boolean fromIme) {
- mInsetsController.show(types);
+ if ((types & WindowInsets.Type.ime()) == 0) {
+ mInsetsController.show(types);
+ } else {
+ super.showInsets(types, fromIme);
+ }
+
}
@Override
public void topFocusedWindowChanged(String packageName) {
- // If both package names are null or both package names are equal, return.
- if (mPackageName == packageName
- || (mPackageName != null && mPackageName.equals(packageName))) {
+ if (Objects.equals(mPackageName, packageName)) {
return;
}
mPackageName = packageName;
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
index 0b164a2e1a51..3fd0852bc0ff 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/CarNavigationBarControllerTest.java
@@ -48,6 +48,10 @@ import org.mockito.MockitoAnnotations;
@SmallTest
public class CarNavigationBarControllerTest extends SysuiTestCase {
+ private static final String TOP_NOTIFICATION_PANEL =
+ "com.android.systemui.car.notification.TopNotificationPanelViewMediator";
+ private static final String BOTTOM_NOTIFICATION_PANEL =
+ "com.android.systemui.car.notification.BottomNotificationPanelViewMediator";
private CarNavigationBarController mCarNavigationBar;
private NavigationBarViewFactory mNavigationBarViewFactory;
private TestableResources mTestableResources;
@@ -117,6 +121,11 @@ public class CarNavigationBarControllerTest extends SysuiTestCase {
@Test
public void testGetTopWindow_topDisabled_returnsNull() {
mTestableResources.addOverride(R.bool.config_enableTopNavigationBar, false);
+ mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
+ // If Top Notification Panel is used but top navigation bar is not enabled, SystemUI is
+ // expected to crash.
+ mTestableResources.addOverride(R.string.config_notificationPanelViewMediator,
+ BOTTOM_NOTIFICATION_PANEL);
mCarNavigationBar = createNavigationBarController();
ViewGroup window = mCarNavigationBar.getTopWindow();
@@ -148,6 +157,11 @@ public class CarNavigationBarControllerTest extends SysuiTestCase {
@Test
public void testGetBottomWindow_bottomDisabled_returnsNull() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, false);
+ mTestableResources.addOverride(R.bool.config_enableTopNavigationBar, true);
+ // If Bottom Notification Panel is used but bottom navigation bar is not enabled,
+ // SystemUI is expected to crash.
+ mTestableResources.addOverride(R.string.config_notificationPanelViewMediator,
+ TOP_NOTIFICATION_PANEL);
mCarNavigationBar = createNavigationBarController();
ViewGroup window = mCarNavigationBar.getBottomWindow();
@@ -237,6 +251,28 @@ public class CarNavigationBarControllerTest extends SysuiTestCase {
}
@Test
+ public void testSetTopWindowVisibility_setTrue_isVisible() {
+ mTestableResources.addOverride(R.bool.config_enableTopNavigationBar, true);
+ mCarNavigationBar = createNavigationBarController();
+
+ ViewGroup window = mCarNavigationBar.getTopWindow();
+ mCarNavigationBar.setTopWindowVisibility(View.VISIBLE);
+
+ assertThat(window.getVisibility()).isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void testSetTopWindowVisibility_setFalse_isGone() {
+ mTestableResources.addOverride(R.bool.config_enableTopNavigationBar, true);
+ mCarNavigationBar = createNavigationBarController();
+
+ ViewGroup window = mCarNavigationBar.getTopWindow();
+ mCarNavigationBar.setTopWindowVisibility(View.GONE);
+
+ assertThat(window.getVisibility()).isEqualTo(View.GONE);
+ }
+
+ @Test
public void testSetBottomWindowVisibility_setTrue_isVisible() {
mTestableResources.addOverride(R.bool.config_enableBottomNavigationBar, true);
mCarNavigationBar = createNavigationBarController();
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java
index 8b1589913d1d..96f05045cd38 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/navigationbar/SystemBarConfigsTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.car.navigationbar;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -31,7 +32,14 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.car.CarDeviceProvisionedController;
import com.android.systemui.car.CarSystemUiTest;
+import com.android.systemui.car.notification.NotificationPanelViewController;
+import com.android.systemui.car.notification.NotificationPanelViewMediator;
+import com.android.systemui.car.notification.PowerManagerHelper;
+import com.android.systemui.car.notification.TopNotificationPanelViewMediator;
+import com.android.systemui.statusbar.policy.ConfigurationController;
import org.junit.Before;
import org.junit.Test;
@@ -92,6 +100,43 @@ public class SystemBarConfigsTest extends SysuiTestCase {
mSystemBarConfigs = new SystemBarConfigs(mResources);
}
+ @Test(expected = RuntimeException.class)
+ public void onInit_hideBottomSystemBarForKeyboardValueDoNotSync_throwsRuntimeException() {
+ when(mResources.getBoolean(R.bool.config_hideBottomSystemBarForKeyboard)).thenReturn(false);
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard)).thenReturn(
+ true);
+
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ }
+
+ @Test
+ public void onInit_topNotifPanelViewMediatorUsed_topBarEnabled_doesNotThrowException() {
+ when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(true);
+ when(mResources.getString(R.string.config_notificationPanelViewMediator)).thenReturn(
+ TestTopNotificationPanelViewMediator.class.getName());
+
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void onInit_topNotifPanelViewMediatorUsed_topBarNotEnabled_throwsRuntimeException() {
+ when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(false);
+ when(mResources.getString(R.string.config_notificationPanelViewMediator)).thenReturn(
+ TestTopNotificationPanelViewMediator.class.getName());
+
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ }
+
+ @Test
+ public void onInit_notificationPanelViewMediatorUsed_topBarNotEnabled_doesNotThrowException() {
+ when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(false);
+ when(mResources.getString(R.string.config_notificationPanelViewMediator)).thenReturn(
+ NotificationPanelViewMediator.class.getName());
+
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+ }
+
@Test
public void getTopSystemBarLayoutParams_topBarEnabled_returnsTopSystemBarLayoutParams() {
mSystemBarConfigs = new SystemBarConfigs(mResources);
@@ -112,6 +157,26 @@ public class SystemBarConfigsTest extends SysuiTestCase {
}
@Test
+ public void getTopSystemBarHideForKeyboard_hideBarForKeyboard_returnsTrue() {
+ when(mResources.getBoolean(R.bool.config_hideTopSystemBarForKeyboard)).thenReturn(true);
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+
+ boolean hideKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.TOP);
+
+ assertTrue(hideKeyboard);
+ }
+
+ @Test
+ public void getTopSystemBarHideForKeyboard_topBarNotEnabled_returnsFalse() {
+ when(mResources.getBoolean(R.bool.config_enableTopNavigationBar)).thenReturn(false);
+ mSystemBarConfigs = new SystemBarConfigs(mResources);
+
+ boolean hideKeyboard = mSystemBarConfigs.getHideForKeyboardBySide(SystemBarConfigs.TOP);
+
+ assertFalse(hideKeyboard);
+ }
+
+ @Test
public void topSystemBarHasHigherZOrderThanHuns_topSystemBarIsNavigationBarPanelType() {
when(mResources.getInteger(R.integer.config_topSystemBarZOrder)).thenReturn(
SystemBarConfigs.getHunZOrder() + 1);
@@ -158,5 +223,30 @@ public class SystemBarConfigsTest extends SysuiTestCase {
when(mResources.getInteger(R.integer.config_bottomSystemBarZOrder)).thenReturn(10);
when(mResources.getInteger(R.integer.config_leftSystemBarZOrder)).thenReturn(2);
when(mResources.getInteger(R.integer.config_rightSystemBarZOrder)).thenReturn(3);
+
+ when(mResources.getBoolean(R.bool.config_hideTopSystemBarForKeyboard)).thenReturn(false);
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_automotiveHideNavBarForKeyboard)).thenReturn(
+ false);
+ when(mResources.getBoolean(R.bool.config_hideLeftSystemBarForKeyboard)).thenReturn(
+ false);
+ when(mResources.getBoolean(R.bool.config_hideRightSystemBarForKeyboard)).thenReturn(
+ false);
+ }
+
+ // Intentionally using a subclass of TopNotificationPanelViewMediator for testing purposes to
+ // ensure that OEM's will be able to implement and use their own NotificationPanelViewMediator.
+ private class TestTopNotificationPanelViewMediator extends
+ TopNotificationPanelViewMediator {
+ TestTopNotificationPanelViewMediator(
+ CarNavigationBarController carNavigationBarController,
+ NotificationPanelViewController notificationPanelViewController,
+ PowerManagerHelper powerManagerHelper,
+ BroadcastDispatcher broadcastDispatcher,
+ CarDeviceProvisionedController carDeviceProvisionedController,
+ ConfigurationController configurationController) {
+ super(carNavigationBarController, notificationPanelViewController, powerManagerHelper,
+ broadcastDispatcher, carDeviceProvisionedController, configurationController);
+ }
}
}
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayPanelViewControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayPanelViewControllerTest.java
index 7311cdb68a3c..23e21e4cbed6 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayPanelViewControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayPanelViewControllerTest.java
@@ -224,18 +224,6 @@ public class OverlayPanelViewControllerTest extends SysuiTestCase {
}
@Test
- public void animateCollapsePanel_removesWindowFocus() {
- mOverlayPanelViewController.inflate(mBaseLayout);
- mOverlayPanelViewController.setShouldAnimateCollapsePanel(true);
- mOverlayPanelViewController.setPanelExpanded(true);
- mOverlayPanelViewController.setPanelVisible(true);
-
- mOverlayPanelViewController.animateCollapsePanel();
-
- verify(mOverlayViewGlobalStateController).setWindowFocusable(false);
- }
-
- @Test
public void animateExpandPanel_shouldNotAnimateExpandPanel_doesNotExpand() {
mOverlayPanelViewController.inflate(mBaseLayout);
mOverlayPanelViewController.setShouldAnimateExpandPanel(false);
@@ -365,14 +353,6 @@ public class OverlayPanelViewControllerTest extends SysuiTestCase {
}
@Test
- public void setPanelVisible_setTrue_setWindowFocusable() {
- mOverlayPanelViewController.inflate(mBaseLayout);
- mOverlayPanelViewController.setPanelVisible(true);
-
- verify(mOverlayViewGlobalStateController).setWindowFocusable(true);
- }
-
- @Test
public void setPanelVisible_setFalse_windowVisible_setsWindowNotVisible() {
mOverlayPanelViewController.inflate(mBaseLayout);
when(mOverlayViewGlobalStateController.isWindowVisible()).thenReturn(true);
@@ -404,15 +384,6 @@ public class OverlayPanelViewControllerTest extends SysuiTestCase {
}
@Test
- public void setPanelVisible_setFalse_setWindowNotFocusable() {
- mOverlayPanelViewController.inflate(mBaseLayout);
-
- mOverlayPanelViewController.setPanelVisible(false);
-
- verify(mOverlayViewGlobalStateController).setWindowFocusable(false);
- }
-
- @Test
public void dragOpenTouchListener_isNotInflated_inflatesView() {
when(mCarDeviceProvisionedController.isCurrentUserFullySetup()).thenReturn(true);
assertThat(mOverlayPanelViewController.isInflated()).isFalse();
diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java
index ff286650ea50..294aa0d3cf9b 100644
--- a/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java
+++ b/packages/CarSystemUI/tests/src/com/android/systemui/car/window/OverlayViewGlobalStateControllerTest.java
@@ -108,9 +108,54 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
}
@Test
+ public void showView_nothingVisible_windowNotFocusable_shouldShowNavBar_navBarsVisible() {
+ setupOverlayViewController1();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(false);
+ when(mOverlayViewController1.shouldShowNavigationBarInsets()).thenReturn(true);
+
+ mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
+
+ verify(mWindowInsetsController).show(navigationBars());
+ }
+
+ @Test
+ public void showView_nothingVisible_windowNotFocusable_shouldHideNavBar_notHidden() {
+ setupOverlayViewController1();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(false);
+ when(mOverlayViewController1.shouldShowNavigationBarInsets()).thenReturn(false);
+
+ mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
+
+ verify(mWindowInsetsController, never()).hide(navigationBars());
+ }
+
+ @Test
+ public void showView_nothingVisible_windowNotFocusable_shouldShowStatusBar_statusBarsVisible() {
+ setupOverlayViewController1();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(false);
+ when(mOverlayViewController1.shouldShowStatusBarInsets()).thenReturn(true);
+
+ mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
+
+ verify(mWindowInsetsController).show(statusBars());
+ }
+
+ @Test
+ public void showView_nothingVisible_windowNotFocusable_shouldHideStatusBar_notHidden() {
+ setupOverlayViewController1();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(false);
+ when(mOverlayViewController1.shouldShowStatusBarInsets()).thenReturn(false);
+
+ mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
+
+ verify(mWindowInsetsController, never()).hide(statusBars());
+ }
+
+ @Test
public void showView_nothingAlreadyShown_shouldShowNavBarFalse_navigationBarsHidden() {
setupOverlayViewController1();
- when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(false);
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController1.shouldShowNavigationBarInsets()).thenReturn(false);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
@@ -120,7 +165,8 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void showView_nothingAlreadyShown_shouldShowNavBarTrue_navigationBarsShown() {
setupOverlayViewController1();
- when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(true);
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController1.shouldShowNavigationBarInsets()).thenReturn(true);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
@@ -130,7 +176,8 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void showView_nothingAlreadyShown_shouldShowStatusBarFalse_statusBarsHidden() {
setupOverlayViewController1();
- when(mOverlayViewController1.shouldShowStatusBar()).thenReturn(false);
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController1.shouldShowStatusBarInsets()).thenReturn(false);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
@@ -140,7 +187,8 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void showView_nothingAlreadyShown_shouldShowStatusBarTrue_statusBarsShown() {
setupOverlayViewController1();
- when(mOverlayViewController1.shouldShowStatusBar()).thenReturn(true);
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController1.shouldShowStatusBarInsets()).thenReturn(true);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
@@ -201,9 +249,11 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void showView_newHighestZOrder_shouldShowNavBarFalse_navigationBarsHidden() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
- when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(false);
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
+ when(mOverlayViewController2.shouldShowNavigationBarInsets()).thenReturn(false);
reset(mWindowInsetsController);
mOverlayViewGlobalStateController.showView(mOverlayViewController2, mRunnable);
@@ -214,9 +264,11 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void showView_newHighestZOrder_shouldShowNavBarTrue_navigationBarsShown() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
- when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(true);
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
+ when(mOverlayViewController2.shouldShowNavigationBarInsets()).thenReturn(true);
mOverlayViewGlobalStateController.showView(mOverlayViewController2, mRunnable);
@@ -226,9 +278,11 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void showView_newHighestZOrder_shouldShowStatusBarFalse_statusBarsHidden() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
- when(mOverlayViewController2.shouldShowStatusBar()).thenReturn(false);
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
+ when(mOverlayViewController2.shouldShowStatusBarInsets()).thenReturn(false);
reset(mWindowInsetsController);
mOverlayViewGlobalStateController.showView(mOverlayViewController2, mRunnable);
@@ -239,9 +293,11 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void showView_newHighestZOrder_shouldShowStatusBarTrue_statusBarsShown() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
- when(mOverlayViewController2.shouldShowStatusBar()).thenReturn(true);
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
+ when(mOverlayViewController2.shouldShowStatusBarInsets()).thenReturn(true);
mOverlayViewGlobalStateController.showView(mOverlayViewController2, mRunnable);
@@ -289,9 +345,11 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void showView_oldHighestZOrder_shouldShowNavBarFalse_navigationBarsHidden() {
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(true);
- when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(false);
+ when(mOverlayViewController1.shouldShowNavigationBarInsets()).thenReturn(true);
+ when(mOverlayViewController2.shouldShowNavigationBarInsets()).thenReturn(false);
reset(mWindowInsetsController);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
@@ -302,9 +360,11 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void showView_oldHighestZOrder_shouldShowNavBarTrue_navigationBarsShown() {
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(false);
- when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(true);
+ when(mOverlayViewController1.shouldShowNavigationBarInsets()).thenReturn(false);
+ when(mOverlayViewController2.shouldShowNavigationBarInsets()).thenReturn(true);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
@@ -314,9 +374,11 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void showView_oldHighestZOrder_shouldShowStatusBarFalse_statusBarsHidden() {
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController1.shouldShowStatusBar()).thenReturn(true);
- when(mOverlayViewController2.shouldShowStatusBar()).thenReturn(false);
+ when(mOverlayViewController1.shouldShowStatusBarInsets()).thenReturn(true);
+ when(mOverlayViewController2.shouldShowStatusBarInsets()).thenReturn(false);
reset(mWindowInsetsController);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
@@ -327,9 +389,11 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void showView_oldHighestZOrder_shouldShowStatusBarTrue_statusBarsShown() {
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController1.shouldShowStatusBar()).thenReturn(false);
- when(mOverlayViewController2.shouldShowStatusBar()).thenReturn(true);
+ when(mOverlayViewController1.shouldShowStatusBarInsets()).thenReturn(false);
+ when(mOverlayViewController2.shouldShowStatusBarInsets()).thenReturn(true);
mOverlayViewGlobalStateController.showView(mOverlayViewController1, mRunnable);
@@ -512,10 +576,12 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void hideView_newHighestZOrder_shouldShowNavBarFalse_navigationBarHidden() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(false);
+ when(mOverlayViewController1.shouldShowNavigationBarInsets()).thenReturn(false);
reset(mWindowInsetsController);
mOverlayViewGlobalStateController.hideView(mOverlayViewController2, mRunnable);
@@ -526,10 +592,13 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void hideView_newHighestZOrder_shouldShowNavBarTrue_navigationBarShown() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController1.shouldShowNavigationBar()).thenReturn(true);
+ when(mOverlayViewController1.shouldShowNavigationBarInsets()).thenReturn(true);
+ reset(mWindowInsetsController);
mOverlayViewGlobalStateController.hideView(mOverlayViewController2, mRunnable);
@@ -539,10 +608,12 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void hideView_newHighestZOrder_shouldShowStatusBarFalse_statusBarHidden() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController1.shouldShowStatusBar()).thenReturn(false);
+ when(mOverlayViewController1.shouldShowStatusBarInsets()).thenReturn(false);
reset(mWindowInsetsController);
mOverlayViewGlobalStateController.hideView(mOverlayViewController2, mRunnable);
@@ -553,10 +624,13 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void hideView_newHighestZOrder_shouldShowStatusBarTrue_statusBarShown() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController1.shouldShowStatusBar()).thenReturn(true);
+ when(mOverlayViewController1.shouldShowStatusBarInsets()).thenReturn(true);
+ reset(mWindowInsetsController);
mOverlayViewGlobalStateController.hideView(mOverlayViewController2, mRunnable);
@@ -593,10 +667,12 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void hideView_oldHighestZOrder_shouldShowNavBarFalse_navigationBarHidden() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(false);
+ when(mOverlayViewController2.shouldShowNavigationBarInsets()).thenReturn(false);
reset(mWindowInsetsController);
mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
@@ -607,10 +683,12 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void hideView_oldHighestZOrder_shouldShowNavBarTrue_navigationBarShown() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController2.shouldShowNavigationBar()).thenReturn(true);
+ when(mOverlayViewController2.shouldShowNavigationBarInsets()).thenReturn(true);
mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
@@ -620,10 +698,12 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void hideView_oldHighestZOrder_shouldShowStatusBarFalse_statusBarHidden() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController2.shouldShowStatusBar()).thenReturn(false);
+ when(mOverlayViewController2.shouldShowStatusBarInsets()).thenReturn(false);
reset(mWindowInsetsController);
mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
@@ -634,10 +714,12 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void hideView_oldHighestZOrder_shouldShowStatusBarTrue_statusBarShown() {
setupOverlayViewController1();
- setOverlayViewControllerAsShowing(mOverlayViewController1);
setupOverlayViewController2();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
+ when(mOverlayViewController2.shouldFocusWindow()).thenReturn(true);
+ setOverlayViewControllerAsShowing(mOverlayViewController1);
setOverlayViewControllerAsShowing(mOverlayViewController2);
- when(mOverlayViewController2.shouldShowStatusBar()).thenReturn(true);
+ when(mOverlayViewController2.shouldShowStatusBarInsets()).thenReturn(true);
mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
@@ -673,6 +755,7 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void hideView_viewControllerOnlyShown_navigationBarShown() {
setupOverlayViewController1();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
setOverlayViewControllerAsShowing(mOverlayViewController1);
mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
@@ -683,6 +766,7 @@ public class OverlayViewGlobalStateControllerTest extends SysuiTestCase {
@Test
public void hideView_viewControllerOnlyShown_statusBarShown() {
setupOverlayViewController1();
+ when(mOverlayViewController1.shouldFocusWindow()).thenReturn(true);
setOverlayViewControllerAsShowing(mOverlayViewController1);
mOverlayViewGlobalStateController.hideView(mOverlayViewController1, mRunnable);
diff --git a/packages/DynamicSystemInstallationService/res/values-nl/strings.xml b/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
index 47eeb839c6dc..2b9fa414dcc5 100644
--- a/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values-nl/strings.xml
@@ -2,7 +2,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="keyguard_description" msgid="8582605799129954556">"Geef je wachtwoord op en ga door naar \'Dynamische systeemupdates\'"</string>
- <string name="notification_install_completed" msgid="6252047868415172643">"Dynamisch systeem is gereed. Start je apparaat opnieuw op om het te gebruiken."</string>
+ <string name="notification_install_completed" msgid="6252047868415172643">"Dynamisch systeem is klaar. Start je apparaat opnieuw op om het te gebruiken."</string>
<string name="notification_install_inprogress" msgid="7383334330065065017">"Installatie wordt uitgevoerd"</string>
<string name="notification_install_failed" msgid="4066039210317521404">"Installatie mislukt"</string>
<string name="notification_image_validation_failed" msgid="2720357826403917016">"Valideren van afbeelding mislukt. Installatie afbreken."</string>
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index f42bf1982b36..11d1b0a9ef2a 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -483,6 +483,13 @@ public class ExternalStorageProvider extends FileSystemProvider {
}
@Override
+ protected void onDocIdDeleted(String docId) {
+ Uri uri = DocumentsContract.buildDocumentUri(AUTHORITY, docId);
+ getContext().revokeUriPermission(uri, ~0);
+ }
+
+
+ @Override
public Cursor queryRoots(String[] projection) throws FileNotFoundException {
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
synchronized (mRootsLock) {
diff --git a/packages/PackageInstaller/res/values-ar/strings.xml b/packages/PackageInstaller/res/values-ar/strings.xml
index 87f89ce192c4..c840374d3f6b 100644
--- a/packages/PackageInstaller/res/values-ar/strings.xml
+++ b/packages/PackageInstaller/res/values-ar/strings.xml
@@ -57,7 +57,7 @@
<string name="uninstall_application_text_all_users" msgid="575491774380227119">"هل تريد إزالة هذا التطبيق "<b>"لكل"</b>" المستخدمين؟ ستتم إزالة التطبيق وبياناته من "<b>"كل"</b>" المستخدمين على هذا الجهاز."</string>
<string name="uninstall_application_text_user" msgid="498072714173920526">"هل تريد إزالة هذا التطبيق للمستخدم <xliff:g id="USERNAME">%1$s</xliff:g>؟"</string>
<string name="uninstall_update_text" msgid="863648314632448705">"هل تريد استبدال هذا التطبيق بإصدار المصنع؟ ستتم إزالة جميع البيانات."</string>
- <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"هل تريد استبدال هذا التطبيق بإصدار المصنع؟ ستتم إزالة جميع البيانات. وسيؤثر هذا في جميع مستخدمي هذا الجهاز، بما في ذلك من لديهم ملفات شخصية للعمل."</string>
+ <string name="uninstall_update_text_multiuser" msgid="8992883151333057227">"هل تريد إعادة ضبط هذا التطبيق على الإعدادات الأصلية؟ سؤدي ذلك إلى إزالة جميع البيانات، كما سيؤثر على جميع مستخدمي هذا الجهاز، بما في ذلك من لديهم ملفات شخصية للعمل."</string>
<string name="uninstall_keep_data" msgid="7002379587465487550">"الاحتفاظ بالحجم <xliff:g id="SIZE">%1$s</xliff:g> من بيانات التطبيق."</string>
<string name="uninstalling_notification_channel" msgid="840153394325714653">"عمليات إلغاء التثبيت الجارية"</string>
<string name="uninstall_failure_notification_channel" msgid="1136405866767576588">"عمليات إلغاء التثبيت غير الناجحة"</string>
diff --git a/packages/PackageInstaller/res/values-nl/strings.xml b/packages/PackageInstaller/res/values-nl/strings.xml
index 108c86fe8369..d3a958922d1c 100644
--- a/packages/PackageInstaller/res/values-nl/strings.xml
+++ b/packages/PackageInstaller/res/values-nl/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_name" msgid="7488448184431507488">"Pakket-installatie"</string>
<string name="install" msgid="711829760615509273">"Installeren"</string>
- <string name="done" msgid="6632441120016885253">"Gereed"</string>
+ <string name="done" msgid="6632441120016885253">"Klaar"</string>
<string name="cancel" msgid="1018267193425558088">"Annuleren"</string>
<string name="installing" msgid="4921993079741206516">"Installeren…"</string>
<string name="installing_app" msgid="1165095864863849422">"<xliff:g id="PACKAGE_LABEL">%1$s</xliff:g> installeren…"</string>
diff --git a/packages/PrintSpooler/res/values-as/strings.xml b/packages/PrintSpooler/res/values-as/strings.xml
index a93fceb87959..b6b287ff66aa 100644
--- a/packages/PrintSpooler/res/values-as/strings.xml
+++ b/packages/PrintSpooler/res/values-as/strings.xml
@@ -47,7 +47,7 @@
<string name="savetopdf_button" msgid="2976186791686924743">"PDFৰ জৰিয়তে ছেভ কৰক"</string>
<string name="print_options_expanded" msgid="6944679157471691859">"প্ৰিণ্ট বিকল্পসমূহ বিস্তাৰ কৰা হ’ল"</string>
<string name="print_options_collapsed" msgid="7455930445670414332">"প্ৰিণ্ট বিকল্পসমূহ সংকুচিত কৰা হ’ল"</string>
- <string name="search" msgid="5421724265322228497">"সন্ধান কৰক"</string>
+ <string name="search" msgid="5421724265322228497">"Search"</string>
<string name="all_printers_label" msgid="3178848870161526399">"সকলো প্ৰিণ্টাৰ"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"সেৱা যোগ কৰক"</string>
<string name="print_search_box_shown_utterance" msgid="7967404953901376090">"সন্ধান বাকচটো দেখুওৱা হ’ল"</string>
diff --git a/packages/PrintSpooler/res/values-bn/strings.xml b/packages/PrintSpooler/res/values-bn/strings.xml
index 637becbe23f0..b2e1eed85f0c 100644
--- a/packages/PrintSpooler/res/values-bn/strings.xml
+++ b/packages/PrintSpooler/res/values-bn/strings.xml
@@ -47,7 +47,7 @@
<string name="savetopdf_button" msgid="2976186791686924743">"পিডিএফ হিসাবে সেভ করুন"</string>
<string name="print_options_expanded" msgid="6944679157471691859">"প্রিন্ট বিকল্প প্রসারিত হয়েছে"</string>
<string name="print_options_collapsed" msgid="7455930445670414332">"প্রিন্ট বিকল্প সংকুচিত হয়েছে"</string>
- <string name="search" msgid="5421724265322228497">"খুঁজুন"</string>
+ <string name="search" msgid="5421724265322228497">"সার্চ"</string>
<string name="all_printers_label" msgid="3178848870161526399">"সমস্ত প্রিন্টার"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"পরিষেবা যোগ করুন"</string>
<string name="print_search_box_shown_utterance" msgid="7967404953901376090">"সার্চ বাক্স দেখানো হচ্ছে"</string>
diff --git a/packages/PrintSpooler/res/values-fa/strings.xml b/packages/PrintSpooler/res/values-fa/strings.xml
index 596947dfb6dc..719fc9219450 100644
--- a/packages/PrintSpooler/res/values-fa/strings.xml
+++ b/packages/PrintSpooler/res/values-fa/strings.xml
@@ -31,7 +31,7 @@
<string name="template_all_pages" msgid="3322235982020148762">"همه <xliff:g id="PAGE_COUNT">%1$s</xliff:g> صفحه"</string>
<string name="template_page_range" msgid="428638530038286328">"محدوده <xliff:g id="PAGE_COUNT">%1$s</xliff:g> صفحه"</string>
<string name="pages_range_example" msgid="8558694453556945172">"‏‏‎مثلاً ۱—۵،‏۹،۷—۱۰"</string>
- <string name="print_preview" msgid="8010217796057763343">"پیش‌نمایش چاپ"</string>
+ <string name="print_preview" msgid="8010217796057763343">"پیش‌نمای چاپ"</string>
<string name="install_for_print_preview" msgid="6366303997385509332">"‏نصب نمایشگر PDF برای پیش‌نمایش"</string>
<string name="printing_app_crashed" msgid="854477616686566398">"برنامه چاپ خراب شد"</string>
<string name="generating_print_job" msgid="3119608742651698916">"در حال ایجاد کار چاپ"</string>
diff --git a/packages/PrintSpooler/res/values-kn/strings.xml b/packages/PrintSpooler/res/values-kn/strings.xml
index 150ede4f8e62..261fe4b0de9a 100644
--- a/packages/PrintSpooler/res/values-kn/strings.xml
+++ b/packages/PrintSpooler/res/values-kn/strings.xml
@@ -47,7 +47,7 @@
<string name="savetopdf_button" msgid="2976186791686924743">"PDF ಗೆ ಉಳಿಸು"</string>
<string name="print_options_expanded" msgid="6944679157471691859">"ಪ್ರಿಂಟ್ ಆಯ್ಕೆಗಳನ್ನು ವಿಸ್ತರಿಸಲಾಗಿದೆ"</string>
<string name="print_options_collapsed" msgid="7455930445670414332">"ಪ್ರಿಂಟ್ ಆಯ್ಕೆಗಳನ್ನು ಮುಚ್ಚಲಾಗಿದೆ"</string>
- <string name="search" msgid="5421724265322228497">"ಹುಡುಕಿ"</string>
+ <string name="search" msgid="5421724265322228497">"Search"</string>
<string name="all_printers_label" msgid="3178848870161526399">"ಎಲ್ಲಾ ಪ್ರಿಂಟರ್‌ಗಳು"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"ಸೇವೆಯನ್ನು ಸೇರಿಸು"</string>
<string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ಹುಡುಕಾಟ ಪೆಟ್ಟಿಗೆಯನ್ನು ತೋರಿಸಲಾಗಿದೆ"</string>
diff --git a/packages/PrintSpooler/res/values-ml/strings.xml b/packages/PrintSpooler/res/values-ml/strings.xml
index dbcd34b1360d..73af95d2e117 100644
--- a/packages/PrintSpooler/res/values-ml/strings.xml
+++ b/packages/PrintSpooler/res/values-ml/strings.xml
@@ -47,7 +47,7 @@
<string name="savetopdf_button" msgid="2976186791686924743">"PDF-ൽ സംരക്ഷിക്കുക"</string>
<string name="print_options_expanded" msgid="6944679157471691859">"പ്രിന്റ് ചെയ്യാനുള്ള ഓപ്‌ഷനുകൾ വിപുലീകരിച്ചു"</string>
<string name="print_options_collapsed" msgid="7455930445670414332">"പ്രിന്റ് ചെയ്യാനുള്ള ഓപ്‌ഷനുകൾ ചുരുക്കി"</string>
- <string name="search" msgid="5421724265322228497">"തിരയൽ"</string>
+ <string name="search" msgid="5421724265322228497">"Search"</string>
<string name="all_printers_label" msgid="3178848870161526399">"എല്ലാ പ്രിന്ററുകളും"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"സേവനം ചേർക്കുക"</string>
<string name="print_search_box_shown_utterance" msgid="7967404953901376090">"തിരയൽ ബോക്‌സ് ദൃശ്യമാക്കിയിരിക്കുന്നു"</string>
diff --git a/packages/PrintSpooler/res/values-mr/strings.xml b/packages/PrintSpooler/res/values-mr/strings.xml
index 44456b4cae05..4d7e919ad125 100644
--- a/packages/PrintSpooler/res/values-mr/strings.xml
+++ b/packages/PrintSpooler/res/values-mr/strings.xml
@@ -47,7 +47,7 @@
<string name="savetopdf_button" msgid="2976186791686924743">"पीडीएफ वर सेव्ह करा"</string>
<string name="print_options_expanded" msgid="6944679157471691859">"प्रिंट पर्याय विस्तृत झाले"</string>
<string name="print_options_collapsed" msgid="7455930445670414332">"प्रिंट पर्याय संक्षिप्त झाले"</string>
- <string name="search" msgid="5421724265322228497">"शोध"</string>
+ <string name="search" msgid="5421724265322228497">"Search"</string>
<string name="all_printers_label" msgid="3178848870161526399">"सर्व प्रिंटर"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"सेवा जोडा"</string>
<string name="print_search_box_shown_utterance" msgid="7967404953901376090">"शोध बॉक्स दर्शविला"</string>
diff --git a/packages/PrintSpooler/res/values-or/strings.xml b/packages/PrintSpooler/res/values-or/strings.xml
index a1675fa7ca76..7000b95b35d6 100644
--- a/packages/PrintSpooler/res/values-or/strings.xml
+++ b/packages/PrintSpooler/res/values-or/strings.xml
@@ -47,7 +47,7 @@
<string name="savetopdf_button" msgid="2976186791686924743">"PDFରେ ସେଭ୍‍ କରନ୍ତୁ"</string>
<string name="print_options_expanded" msgid="6944679157471691859">"ପ୍ରିଣ୍ଟ ବିକଳ୍ପକୁ ବଡ଼ କରାଯାଇଛି"</string>
<string name="print_options_collapsed" msgid="7455930445670414332">"ପ୍ରିଣ୍ଟ ବିକଳ୍ପକୁ ଛୋଟ କରାଯାଇଛି"</string>
- <string name="search" msgid="5421724265322228497">"ସର୍ଚ୍ଚ କରନ୍ତୁ"</string>
+ <string name="search" msgid="5421724265322228497">"Search"</string>
<string name="all_printers_label" msgid="3178848870161526399">"ସମସ୍ତ ପ୍ରିଣ୍ଟର୍‌"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"ସେବା ଯୋଗ କରନ୍ତୁ"</string>
<string name="print_search_box_shown_utterance" msgid="7967404953901376090">"ସର୍ଚ୍ଚ ବକ୍ସ ଦେଖାଯାଇଛି"</string>
diff --git a/packages/PrintSpooler/res/values-te/strings.xml b/packages/PrintSpooler/res/values-te/strings.xml
index b01b50a60f6b..79944bb9994c 100644
--- a/packages/PrintSpooler/res/values-te/strings.xml
+++ b/packages/PrintSpooler/res/values-te/strings.xml
@@ -47,7 +47,7 @@
<string name="savetopdf_button" msgid="2976186791686924743">"PDF వలె సేవ్ చేయి"</string>
<string name="print_options_expanded" msgid="6944679157471691859">"ముద్రణ ఎంపికలు విస్తరించబడ్డాయి"</string>
<string name="print_options_collapsed" msgid="7455930445670414332">"ముద్రణ ఎంపికలు కుదించబడ్డాయి"</string>
- <string name="search" msgid="5421724265322228497">"వెతుకు"</string>
+ <string name="search" msgid="5421724265322228497">"సెర్చ్"</string>
<string name="all_printers_label" msgid="3178848870161526399">"అన్ని ప్రింటర్‌లు"</string>
<string name="add_print_service_label" msgid="5356702546188981940">"సేవను జోడించు"</string>
<string name="print_search_box_shown_utterance" msgid="7967404953901376090">"శోధన పెట్టె చూపబడింది"</string>
diff --git a/packages/PrintSpooler/res/values-uz/strings.xml b/packages/PrintSpooler/res/values-uz/strings.xml
index d17bce7ae54e..ea0a6ea2f7b8 100644
--- a/packages/PrintSpooler/res/values-uz/strings.xml
+++ b/packages/PrintSpooler/res/values-uz/strings.xml
@@ -100,7 +100,7 @@
</string-array>
<string-array name="orientation_labels">
<item msgid="4061931020926489228">"Tik holat"</item>
- <item msgid="3199660090246166812">"Eniga"</item>
+ <item msgid="3199660090246166812">"Yotiq"</item>
</string-array>
<string name="print_write_error_message" msgid="5787642615179572543">"Faylga yozib bo‘lmadi"</string>
<string name="print_error_default_message" msgid="8602678405502922346">"Xatolik yuz berdi. Qaytadan urining."</string>
diff --git a/packages/SettingsLib/HelpUtils/res/values-te/strings.xml b/packages/SettingsLib/HelpUtils/res/values-te/strings.xml
index ea66717b1e87..82c8613b5c8c 100644
--- a/packages/SettingsLib/HelpUtils/res/values-te/strings.xml
+++ b/packages/SettingsLib/HelpUtils/res/values-te/strings.xml
@@ -17,5 +17,5 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="help_feedback_label" msgid="7106780063063027882">"సహాయం &amp; అభిప్రాయం"</string>
+ <string name="help_feedback_label" msgid="7106780063063027882">"సహాయం &amp; ఫీడ్‌బ్యాక్"</string>
</resources>
diff --git a/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_0.xml b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_0.xml
new file mode 100644
index 000000000000..16e91903084f
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_0.xml
@@ -0,0 +1,31 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="25.50"
+ android:viewportHeight="25.50">
+ <group
+ android:translateX="0.77"
+ android:translateY="0.23" >
+ <path
+ android:pathData="M14,12h6.54l3.12,-3.89c0.39,-0.48 0.29,-1.19 -0.22,-1.54C21.67,5.36 17.55,3 12,3C6.44,3 2.33,5.36 0.56,6.57C0.05,6.92 -0.05,7.63 0.33,8.11L11.16,21.6c0.42,0.53 1.23,0.53 1.66,0L14,20.13V12z"
+ android:fillColor="#FFFFFF"/>
+ <path
+ android:pathData="M22.71,15.67l-1.83,1.83l1.83,1.83c0.38,0.38 0.38,1 0,1.38v0c-0.38,0.38 -1,0.39 -1.38,0l-1.83,-1.83l-1.83,1.83c-0.38,0.38 -1,0.38 -1.38,0l-0.01,-0.01c-0.38,-0.38 -0.38,-1 0,-1.38l1.83,-1.83l-1.82,-1.82c-0.38,-0.38 -0.38,-1 0,-1.38l0.01,-0.01c0.38,-0.38 1,-0.38 1.38,0l1.82,1.82l1.82,-1.82c0.38,-0.38 1,-0.38 1.38,0l0,0C23.09,14.67 23.09,15.29 22.71,15.67z"
+ android:fillColor="#FFFFFF"/>
+ </group>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_1.xml b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_1.xml
new file mode 100644
index 000000000000..4c338c968194
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_1.xml
@@ -0,0 +1,27 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2.01C7.25,2.01 2.97,4.09 0,7.4L7.582,16.625C7.582,16.627 7.58,16.629 7.58,16.631L11.99,22L12,22L13,20.789L13,17.641L13,13.119C12.68,13.039 12.34,13 12,13C10.601,13 9.351,13.64 8.531,14.639L2.699,7.539C5.269,5.279 8.58,4.01 12,4.01C15.42,4.01 18.731,5.279 21.301,7.539L16.811,13L19.4,13L24,7.4C21.03,4.09 16.75,2.01 12,2.01z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_2.xml b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_2.xml
new file mode 100644
index 000000000000..79037dbccf2d
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_2.xml
@@ -0,0 +1,27 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C7.25,2 2.97,4.081 0,7.391L12,22L13,20.779L13,17.631L13,13L16.801,13L18,13L19.391,13L24,7.391C21.03,4.081 16.75,2 12,2zM12,4C14.747,4 17.423,4.819 19.701,6.313C20.259,6.678 20.795,7.085 21.301,7.529L17.389,12.287C16.029,10.868 14.119,9.99 12,9.99C9.88,9.99 7.969,10.869 6.609,12.289L2.699,7.529C5.269,5.269 8.58,4 12,4z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_3.xml b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_3.xml
new file mode 100644
index 000000000000..21ad128f81ff
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_3.xml
@@ -0,0 +1,27 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C7.25,2 2.97,4.081 0,7.391L3.301,11.41L12,22L13,20.779L13,17.631L13,13L16.801,13L19.391,13L20.699,11.41C20.699,11.409 20.698,11.409 20.697,11.408L24,7.391C21.03,4.081 16.75,2 12,2zM12,4C15.42,4 18.731,5.269 21.301,7.529L19.35,9.9C17.43,8.1 14.86,6.99 12,6.99C9.14,6.99 6.57,8.1 4.65,9.9C4.65,9.901 4.649,9.902 4.648,9.902L2.699,7.529C5.269,5.269 8.58,4 12,4z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_4.xml b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_4.xml
new file mode 100644
index 000000000000..2ec5ba30cdc3
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_show_x_wifi_signal_4.xml
@@ -0,0 +1,27 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C7.25,2 2.97,4.08 0,7.39L12,22l1,-1.22V13h6.39L24,7.39C21.03,4.08 16.75,2 12,2z"/>
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M22,16.41L20.59,15l-2.09,2.09L16.41,15L15,16.41l2.09,2.09L15,20.59L16.41,22l2.09,-2.08L20.59,22L22,20.59l-2.08,-2.09L22,16.41z"/>
+</vector>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 9acfa0da7747..0b4538097e41 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -25,7 +25,7 @@
<string name="wifi_remembered" msgid="3266709779723179188">"تم الحفظ"</string>
<string name="wifi_disconnected" msgid="7054450256284661757">"غير متصلة"</string>
<string name="wifi_disabled_generic" msgid="2651916945380294607">"غير مفعّلة"</string>
- <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"‏تعذّرت تهيئة عنوان IP"</string>
+ <string name="wifi_disabled_network_failure" msgid="2660396183242399585">"‏تعذّر إعداد عنوان IP"</string>
<string name="wifi_disabled_by_recommendation_provider" msgid="1302938248432705534">"الجهاز غير متصل بسبب انخفاض جودة الشبكة"</string>
<string name="wifi_disabled_wifi_failure" msgid="8819554899148331100">"‏تعذّر اتصال WiFi"</string>
<string name="wifi_disabled_password_failure" msgid="6892387079613226738">"حدثت مشكلة في المصادقة"</string>
@@ -153,7 +153,7 @@
<string name="unknown" msgid="3544487229740637809">"غير معروف"</string>
<string name="running_process_item_user_label" msgid="3988506293099805796">"المستخدم: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
<string name="launch_defaults_some" msgid="3631650616557252926">"تم ضبط بعض الإعدادات التلقائية"</string>
- <string name="launch_defaults_none" msgid="8049374306261262709">"لم يتم تعيين إعدادات تلقائية"</string>
+ <string name="launch_defaults_none" msgid="8049374306261262709">"لم يتم ضبط إعدادات تلقائية"</string>
<string name="tts_settings" msgid="8130616705989351312">"إعدادات تحويل النص إلى كلام"</string>
<string name="tts_settings_title" msgid="7602210956640483039">"تحويل النص إلى كلام"</string>
<string name="tts_default_rate_title" msgid="3964187817364304022">"معدل سرعة الكلام"</string>
@@ -245,7 +245,7 @@
<string name="confirm_enable_oem_unlock_title" msgid="8249318129774367535">"هل تريد السماح بإلغاء قفل المصنّع الأصلي للجهاز؟"</string>
<string name="confirm_enable_oem_unlock_text" msgid="854131050791011970">"تحذير: لن تعمل ميزات الحماية على هذا الجهاز أثناء تفعيل هذا الإعداد."</string>
<string name="mock_location_app" msgid="6269380172542248304">"اختيار تطبيق الموقع الزائف"</string>
- <string name="mock_location_app_not_set" msgid="6972032787262831155">"لم يتم تعيين تطبيق موقع زائف"</string>
+ <string name="mock_location_app_not_set" msgid="6972032787262831155">"لم يتم ضبط تطبيق موقع زائف"</string>
<string name="mock_location_app_set" msgid="4706722469342913843">"تطبيق الموقع الزائف: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="debug_networking_category" msgid="6829757985772659599">"الشبكات"</string>
<string name="wifi_display_certification" msgid="1805579519992520381">"شهادة عرض شاشة لاسلكي"</string>
@@ -292,8 +292,8 @@
<string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"عندما نتوقف عن رصد أي أخطاء باستخدام المسجِّل الدائم مرة أخرى، يتعين علينا محو بيانات المسجِّل الموجودة على جهازك."</string>
<string name="select_logpersist_title" msgid="447071974007104196">"تخزين بيانات المسجِّل باستمرار على الجهاز"</string>
<string name="select_logpersist_dialog_title" msgid="7745193591195485594">"تحديد مخازن السجلات المؤقتة المراد تخزينها باستمرار على الجهاز"</string>
- <string name="select_usb_configuration_title" msgid="6339801314922294586">"‏حدد تهيئة USB"</string>
- <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"‏حدد تهيئة USB"</string>
+ <string name="select_usb_configuration_title" msgid="6339801314922294586">"‏حدد إعداد USB"</string>
+ <string name="select_usb_configuration_dialog_title" msgid="3579567144722589237">"‏حدد إعداد USB"</string>
<string name="allow_mock_location" msgid="2102650981552527884">"السماح بمواقع وهمية"</string>
<string name="allow_mock_location_summary" msgid="179780881081354579">"السماح بمواقع وهمية"</string>
<string name="debug_view_attributes" msgid="3539609843984208216">"تفعيل فحص سمة العرض"</string>
@@ -318,7 +318,7 @@
<string name="hdcp_checking_dialog_title" msgid="7691060297616217781">"‏تعيين سلوك التحقق من HDCP"</string>
<string name="debug_debugging_category" msgid="535341063709248842">"تصحيح الأخطاء"</string>
<string name="debug_app" msgid="8903350241392391766">"اختيار التطبيق لتصحيحه"</string>
- <string name="debug_app_not_set" msgid="1934083001283807188">"لم يتم تعيين تطبيق لتصحيحه"</string>
+ <string name="debug_app_not_set" msgid="1934083001283807188">"لم يتم ضبط تطبيق لتصحيحه"</string>
<string name="debug_app_set" msgid="6599535090477753651">"تطبيق التصحيح: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="select_application" msgid="2543228890535466325">"اختيار تطبيق"</string>
<string name="no_application" msgid="9038334538870247690">"لا شيء"</string>
@@ -381,9 +381,9 @@
<string name="local_backup_password_title" msgid="4631017948933578709">"كلمة مرور احتياطية للكمبيوتر"</string>
<string name="local_backup_password_summary_none" msgid="7646898032616361714">"النُسخ الاحتياطية الكاملة لسطح المكتب غير محمية في الوقت الحالي"</string>
<string name="local_backup_password_summary_change" msgid="1707357670383995567">"انقر لتغيير كلمة مرور النسخ الاحتياطية الكاملة لسطح المكتب أو إزالتها."</string>
- <string name="local_backup_password_toast_success" msgid="4891666204428091604">"تم تعيين كلمة مرور احتياطية جديدة"</string>
+ <string name="local_backup_password_toast_success" msgid="4891666204428091604">"تم ضبط كلمة مرور احتياطية جديدة"</string>
<string name="local_backup_password_toast_confirmation_mismatch" msgid="2994718182129097733">"كلمة المرور الجديدة وتأكيدها لا يتطابقان"</string>
- <string name="local_backup_password_toast_validation_failure" msgid="714669442363647122">"تعذّر تعيين كلمة مرور احتياطية"</string>
+ <string name="local_backup_password_toast_validation_failure" msgid="714669442363647122">"تعذّر ضبط كلمة مرور احتياطية"</string>
<string name="loading_injected_setting_summary" msgid="8394446285689070348">"جارٍ التحميل…"</string>
<string-array name="color_mode_names">
<item msgid="3836559907767149216">"نابض بالحياة (تلقائي)"</item>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 8f71509772fc..7f6237da9ee0 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -212,7 +212,7 @@
<string name="adb_wireless_settings" msgid="2295017847215680229">"Адладка па Wi-Fi"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Каб праглядаць і выкарыстоўваць даступныя прылады, уключыце адладку па Wi-Fi"</string>
<string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Спалучыць прыладу з дапамогай QR-кода"</string>
- <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Спалучаць новыя прылады з дапамогай сканера QR-кода"</string>
+ <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"Спалучаць новыя прылады з дапамогай сканера QR-кодаў"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"Спалучыць прыладу з дапамогай кода спалучэння"</string>
<string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Спалучаць новыя прылады з дапамогай шасцізначнага кода"</string>
<string name="adb_paired_devices_title" msgid="5268997341526217362">"Спалучаныя прылады"</string>
diff --git a/packages/SettingsLib/res/values-bs/arrays.xml b/packages/SettingsLib/res/values-bs/arrays.xml
index 7c2a0fd0c8e4..775cd15edc0b 100644
--- a/packages/SettingsLib/res/values-bs/arrays.xml
+++ b/packages/SettingsLib/res/values-bs/arrays.xml
@@ -187,7 +187,7 @@
<item msgid="97587758561106269">"Isključeno"</item>
<item msgid="7126170197336963369">"Međuspremnici svih zapisnika"</item>
<item msgid="7167543126036181392">"Međuspremnici svih zapisnika osim radija"</item>
- <item msgid="5135340178556563979">"samo međuspremnik zapisnika kernela"</item>
+ <item msgid="5135340178556563979">"samo međumemorija zapisnika kernela"</item>
</string-array>
<string-array name="window_animation_scale_entries">
<item msgid="2675263395797191850">"Animacija isključena"</item>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index dcdadbdf3454..4a11aa77c7fc 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -400,7 +400,7 @@
<string name="inactive_app_active_summary" msgid="8047630990208722344">"Aktibo. Aldatzeko, sakatu hau."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Egonean moduko aplikazioaren egoera: <xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Abian diren zerbitzuak"</string>
- <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ikusi eta kontrolatu unean abian diren zerbitzuak"</string>
+ <string name="runningservices_settings_summary" msgid="1046080643262665743">"Ikusi eta kontrolatu une honetan abian diren zerbitzuak"</string>
<string name="select_webview_provider_title" msgid="3917815648099445503">"WebView inplementazioa"</string>
<string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"Ezarri WebView inplementazioa"</string>
<string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Jada ez dago erabilgarri aukera hori. Saiatu berriro."</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index f3b22d355b77..3373f815ebaf 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -139,7 +139,7 @@
<string name="accessibility_wifi_signal_full" msgid="7165262794551355617">"‏قدرت سیگنال Wi‑Fi کامل است."</string>
<string name="accessibility_wifi_security_type_none" msgid="162352241518066966">"شبکه باز"</string>
<string name="accessibility_wifi_security_type_secured" msgid="2399774097343238942">"شبکه ایمن"</string>
- <string name="process_kernel_label" msgid="950292573930336765">"‏سیستم عامل Android"</string>
+ <string name="process_kernel_label" msgid="950292573930336765">"‏سیستم‌عامل Android"</string>
<string name="data_usage_uninstalled_apps" msgid="1933665711856171491">"برنامه‌های حذف شده"</string>
<string name="data_usage_uninstalled_apps_users" msgid="5533981546921913295">"برنامه‌ها و کاربران حذف شده"</string>
<string name="data_usage_ota" msgid="7984667793701597001">"به‌روزرسانی‌های سیستم"</string>
@@ -211,8 +211,8 @@
<string name="adb_wireless_error" msgid="721958772149779856">"خطا"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"اشکال‌زدایی بی‌سیم"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"برای مشاهده و استفاده از دستگاه‌های در دسترس، اشکال‌زدایی بی‌سیم را روشن کنید"</string>
- <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"‏مرتبط کردن دستگاه با کد QR"</string>
- <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"‏دستگاه‌های جدید را بااستفاده از اسکنر کد QR مرتبط کنید"</string>
+ <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"مرتبط کردن دستگاه با رمزینه پاسخ‌سریع"</string>
+ <string name="adb_pair_method_qrcode_summary" msgid="7130694277228970888">"دستگاه‌های جدید را بااستفاده از اسکنر رمزینه پاسخ‌سریع مرتبط کنید"</string>
<string name="adb_pair_method_code_title" msgid="1122590300445142904">"مرتبط کردن دستگاه با کد مرتبط‌سازی"</string>
<string name="adb_pair_method_code_summary" msgid="6370414511333685185">"دستگاه‌های جدید را با استفاده از کد شش رقمی مرتبط کنید"</string>
<string name="adb_paired_devices_title" msgid="5268997341526217362">"دستگاه‌های مرتبط‌شده"</string>
@@ -226,12 +226,12 @@
<string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"‏کد مرتبط‌سازی Wi‑Fi"</string>
<string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"مرتبط‌سازی ناموفق"</string>
<string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"مطمئن شوید که دستگاه به همان شبکه متصل باشد."</string>
- <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"‏دستگاه را ازطریق Wi‑Fi و با اسکن کردن کد QR مرتبط کنید"</string>
+ <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"‏دستگاه را ازطریق Wi‑Fi و با اسکن کردن رمزینه پاسخ‌سریع مرتبط کنید"</string>
<string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"مرتبط‌سازی دستگاه…"</string>
- <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"‏مرتبط کردن دستگاه انجام نشد. یا کد QR اشتباه بوده است، یا دستگاه به همان شبکه متصل نیست."</string>
+ <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"مرتبط کردن دستگاه انجام نشد. یا رمزینه پاسخ‌سریع اشتباه بوده است، یا دستگاه به همان شبکه متصل نیست."</string>
<string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"‏نشانی IP و درگاه"</string>
- <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"‏اسکن کد QR"</string>
- <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"‏دستگاه را ازطریق Wi‑Fi و با اسکن کردن کد QR مرتبط کنید"</string>
+ <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"اسکن رمزینه پاسخ‌سریع"</string>
+ <string name="adb_wireless_qrcode_pairing_description" msgid="6014121407143607851">"‏دستگاه را ازطریق Wi‑Fi و با اسکن کردن رمزینه پاسخ‌سریع مرتبط کنید"</string>
<string name="adb_wireless_no_network_msg" msgid="2365795244718494658">"‏لطفاً به شبکه Wi-Fi متصل شوید"</string>
<string name="keywords_adb_wireless" msgid="6507505581882171240">"‏ADB (پل اشکال‌زدایی Android)، اشکال‌زدایی کردن، برنامه‌نویس"</string>
<string name="bugreport_in_power" msgid="8664089072534638709">"میان‌بر گزارش مشکل"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 3261f69b1105..894a14ac3b74 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -487,8 +487,8 @@
<string name="status_unavailable" msgid="5279036186589861608">"અનુપલબ્ધ"</string>
<string name="wifi_status_mac_randomized" msgid="466382542497832189">"MACને રેન્ડમ કરેલ છે"</string>
<plurals name="wifi_tether_connected_summary" formatted="false" msgid="6317236306047306139">
- <item quantity="one">%1$d ઉપકરણ કનેક્ટ કર્યું</item>
- <item quantity="other">%1$d ઉપકરણો કનેક્ટ કર્યા</item>
+ <item quantity="one">%1$d ડિવાઇસ કનેક્ટ કર્યું</item>
+ <item quantity="other">%1$d ડિવાઇસ કનેક્ટ કર્યા</item>
</plurals>
<string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"વધુ સમય."</string>
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"ઓછો સમય."</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 8b92640e9996..ffd95a45b61e 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -57,7 +57,7 @@
<string name="osu_sign_up_complete" msgid="7640183358878916847">"Գրանցումն ավարտված է: Միացում…"</string>
<string name="speed_label_very_slow" msgid="8526005255731597666">"Շատ դանդաղ"</string>
<string name="speed_label_slow" msgid="6069917670665664161">"Դանդաղ"</string>
- <string name="speed_label_okay" msgid="1253594383880810424">"Հաստատել"</string>
+ <string name="speed_label_okay" msgid="1253594383880810424">"Լավ"</string>
<string name="speed_label_medium" msgid="9078405312828606976">"Միջին"</string>
<string name="speed_label_fast" msgid="2677719134596044051">"Արագ"</string>
<string name="speed_label_very_fast" msgid="8215718029533182439">"Շատ արագ"</string>
@@ -493,7 +493,7 @@
<string name="accessibility_manual_zen_more_time" msgid="5141801092071134235">"Ավելացնել ժամանակը:"</string>
<string name="accessibility_manual_zen_less_time" msgid="6828877595848229965">"Պակասեցնել ժամանակը:"</string>
<string name="cancel" msgid="5665114069455378395">"Չեղարկել"</string>
- <string name="okay" msgid="949938843324579502">"Հաստատել"</string>
+ <string name="okay" msgid="949938843324579502">"Եղավ"</string>
<string name="zen_mode_enable_dialog_turn_on" msgid="6418297231575050426">"Միացնել"</string>
<string name="zen_mode_settings_turn_on_dialog_title" msgid="2760567063190790696">"Միացրեք «Չանհանգստացնել» ռեժիմը"</string>
<string name="zen_mode_settings_summary_off" msgid="3832876036123504076">"Երբեք"</string>
diff --git a/packages/SettingsLib/res/values-in/arrays.xml b/packages/SettingsLib/res/values-in/arrays.xml
index 37cf189f26c0..3ab50cc948eb 100644
--- a/packages/SettingsLib/res/values-in/arrays.xml
+++ b/packages/SettingsLib/res/values-in/arrays.xml
@@ -31,7 +31,7 @@
<item msgid="7852381437933824454">"Memutus sambungan..."</item>
<item msgid="5046795712175415059">"Sambungan terputus"</item>
<item msgid="2473654476624070462">"Gagal"</item>
- <item msgid="9146847076036105115">"Dicekal"</item>
+ <item msgid="9146847076036105115">"Diblokir"</item>
<item msgid="4543924085816294893">"Menghindari sambungan buruk untuk sementara"</item>
</string-array>
<string-array name="wifi_status_with_ssid">
diff --git a/packages/SettingsLib/res/values-ja/arrays.xml b/packages/SettingsLib/res/values-ja/arrays.xml
index 743017c82e3a..7a4e71b18ec0 100644
--- a/packages/SettingsLib/res/values-ja/arrays.xml
+++ b/packages/SettingsLib/res/values-ja/arrays.xml
@@ -243,7 +243,7 @@
</string-array>
<string-array name="track_frame_time_entries">
<item msgid="634406443901014984">"OFF"</item>
- <item msgid="1288760936356000927">"バーとして画面に表示"</item>
+ <item msgid="1288760936356000927">"棒グラフとして画面に表示"</item>
<item msgid="5023908510820531131">"<xliff:g id="AS_TYPED_COMMAND">adb shell dumpsys gfxinfo</xliff:g> 内"</item>
</string-array>
<string-array name="debug_hw_overdraw_entries">
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index c4b5f7e7477f..419c18f3b8c6 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -396,8 +396,8 @@
<item msgid="1282170165150762976">"Санарип мазмун үчүн оптималдаштырылган түстөр"</item>
</string-array>
<string name="inactive_apps_title" msgid="5372523625297212320">"Көшүү режиминдеги колдонмолор"</string>
- <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Иштеген жок. Которуштуруу үчүн таптап коюңуз."</string>
- <string name="inactive_app_active_summary" msgid="8047630990208722344">"Иштеп турат. Которуштуруу үчүн таптап коюңуз."</string>
+ <string name="inactive_app_inactive_summary" msgid="3161222402614236260">"Иштеген жок. Күйгүзүү үчүн басып коюңуз."</string>
+ <string name="inactive_app_active_summary" msgid="8047630990208722344">"Иштеп турат. Өчүрүү үчүн басып коюңуз."</string>
<string name="standby_bucket_summary" msgid="5128193447550429600">"Көшүү режиминдеги колдонмонун абалы:<xliff:g id="BUCKET"> %s</xliff:g>"</string>
<string name="runningservices_settings_title" msgid="6460099290493086515">"Иштеп жаткан кызматтар"</string>
<string name="runningservices_settings_summary" msgid="1046080643262665743">"Учурда иштеп жаткан кызматтарды көрүп, көзөмөлдөп турасыз"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index fb7b63410a5f..58d4af1c2c64 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -204,10 +204,10 @@
<string name="tethering_settings_not_available" msgid="266821736434699780">"Поставките за спојување не се достапни за овој корисник"</string>
<string name="apn_settings_not_available" msgid="1147111671403342300">"Поставките за името на пристапната точка не се достапни за овој корисник"</string>
<string name="enable_adb" msgid="8072776357237289039">"Отстранување грешки на USB"</string>
- <string name="enable_adb_summary" msgid="3711526030096574316">"Режим на отстранување грешки кога е поврзано USB"</string>
+ <string name="enable_adb_summary" msgid="3711526030096574316">"Режим за отстранување грешки кога е поврзано USB"</string>
<string name="clear_adb_keys" msgid="3010148733140369917">"Отповикај овластувања за отстранување грешки од USB"</string>
<string name="enable_adb_wireless" msgid="6973226350963971018">"Безжично отстранување грешки"</string>
- <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим на отстранување грешки кога е поврзано Wi‑Fi"</string>
+ <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим за отстранување грешки кога е поврзано Wi‑Fi"</string>
<string name="adb_wireless_error" msgid="721958772149779856">"Грешка"</string>
<string name="adb_wireless_settings" msgid="2295017847215680229">"Безжично отстранување грешки"</string>
<string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"За да ги гледате и користите достапните уреди, вклучете го безжичното отстранување грешки"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 60001a0b0ecd..e252eca5d72a 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -510,7 +510,7 @@
<string name="media_transfer_this_device_name" msgid="2716555073132169240">"ఫోన్ స్పీకర్"</string>
<string name="profile_connect_timeout_subtext" msgid="4043408193005851761">"కనెక్ట్ చేయడంలో సమస్య ఉంది. పరికరాన్ని ఆఫ్ చేసి, ఆపై తిరిగి ఆన్ చేయండి"</string>
<string name="media_transfer_wired_device_name" msgid="4447880899964056007">"వైర్ గల ఆడియో పరికరం"</string>
- <string name="help_label" msgid="3528360748637781274">"సహాయం &amp; అభిప్రాయం"</string>
+ <string name="help_label" msgid="3528360748637781274">"సహాయం &amp; ఫీడ్‌బ్యాక్"</string>
<string name="storage_category" msgid="2287342585424631813">"నిల్వ"</string>
<string name="shared_data_title" msgid="1017034836800864953">"షేర్ చేసిన డేటా"</string>
<string name="shared_data_summary" msgid="5516326713822885652">"షేర్ చేసిన డేటాను చూసి, సవరించండి"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/Utils.java b/packages/SettingsLib/src/com/android/settingslib/Utils.java
index a43412e116c8..b2808061586b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/Utils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/Utils.java
@@ -49,11 +49,19 @@ public class Utils {
private static String sSharedSystemSharedLibPackageName;
static final int[] WIFI_PIE = {
- com.android.internal.R.drawable.ic_wifi_signal_0,
- com.android.internal.R.drawable.ic_wifi_signal_1,
- com.android.internal.R.drawable.ic_wifi_signal_2,
- com.android.internal.R.drawable.ic_wifi_signal_3,
- com.android.internal.R.drawable.ic_wifi_signal_4
+ com.android.internal.R.drawable.ic_wifi_signal_0,
+ com.android.internal.R.drawable.ic_wifi_signal_1,
+ com.android.internal.R.drawable.ic_wifi_signal_2,
+ com.android.internal.R.drawable.ic_wifi_signal_3,
+ com.android.internal.R.drawable.ic_wifi_signal_4
+ };
+
+ static final int[] SHOW_X_WIFI_PIE = {
+ R.drawable.ic_show_x_wifi_signal_0,
+ R.drawable.ic_show_x_wifi_signal_1,
+ R.drawable.ic_show_x_wifi_signal_2,
+ R.drawable.ic_show_x_wifi_signal_3,
+ R.drawable.ic_show_x_wifi_signal_4
};
public static void updateLocationEnabled(Context context, boolean enabled, int userId,
@@ -353,10 +361,22 @@ public class Utils {
* @throws IllegalArgumentException if an invalid RSSI level is given.
*/
public static int getWifiIconResource(int level) {
+ return getWifiIconResource(false /* showX */, level);
+ }
+
+ /**
+ * Returns the Wifi icon resource for a given RSSI level.
+ *
+ * @param showX True if a connected Wi-Fi network has the problem which should show Pie+x
+ * signal icon to users.
+ * @param level The number of bars to show (0-4)
+ * @throws IllegalArgumentException if an invalid RSSI level is given.
+ */
+ public static int getWifiIconResource(boolean showX, int level) {
if (level < 0 || level >= WIFI_PIE.length) {
throw new IllegalArgumentException("No Wifi icon found for level: " + level);
}
- return WIFI_PIE[level];
+ return showX ? SHOW_X_WIFI_PIE[level] : WIFI_PIE[level];
}
public static int getDefaultStorageManagerDaysToRetain(Resources resources) {
diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
index 9d06c8467e41..72a6074ff89c 100644
--- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java
@@ -465,7 +465,16 @@ public class LocalMediaManager implements BluetoothCallback {
synchronized (mMediaDevicesLock) {
mMediaDevices.clear();
mMediaDevices.addAll(devices);
- mMediaDevices.addAll(buildDisconnectedBluetoothDevice());
+ // Add disconnected bluetooth devices only when phone output device is available.
+ for (MediaDevice device : devices) {
+ final int type = device.getDeviceType();
+ if (type == MediaDevice.MediaDeviceType.TYPE_USB_C_AUDIO_DEVICE
+ || type == MediaDevice.MediaDeviceType.TYPE_3POINT5_MM_AUDIO_DEVICE
+ || type == MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE) {
+ mMediaDevices.addAll(buildDisconnectedBluetoothDevice());
+ break;
+ }
+ }
}
final MediaDevice infoMediaDevice = mInfoMediaManager.getCurrentConnectedDevice();
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java
index a53bc9f966d2..aad0d3af6626 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiEntryPreference.java
@@ -64,6 +64,7 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt
private final IconInjector mIconInjector;
private WifiEntry mWifiEntry;
private int mLevel = -1;
+ private boolean mShowX; // Shows the Wi-Fi signl icon of Pie+x when it's true.
private CharSequence mContentDescription;
private OnButtonClickListener mOnButtonClickListener;
@@ -136,9 +137,11 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt
public void refresh() {
setTitle(mWifiEntry.getTitle());
final int level = mWifiEntry.getLevel();
- if (level != mLevel) {
+ final boolean showX = mWifiEntry.shouldShowXLevelIcon();
+ if (level != mLevel || showX != mShowX) {
mLevel = level;
- updateIcon(mLevel);
+ mShowX = showX;
+ updateIcon(mShowX, mLevel);
notifyChanged();
}
@@ -184,13 +187,13 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt
}
- private void updateIcon(int level) {
+ private void updateIcon(boolean showX, int level) {
if (level == -1) {
setIcon(null);
return;
}
- final Drawable drawable = mIconInjector.getIcon(level);
+ final Drawable drawable = mIconInjector.getIcon(showX, level);
if (drawable != null) {
drawable.setTintList(Utils.getColorAttr(getContext(),
android.R.attr.colorControlNormal));
@@ -260,8 +263,8 @@ public class WifiEntryPreference extends Preference implements WifiEntry.WifiEnt
mContext = context;
}
- public Drawable getIcon(int level) {
- return mContext.getDrawable(Utils.getWifiIconResource(level));
+ public Drawable getIcon(boolean showX, int level) {
+ return mContext.getDrawable(Utils.getWifiIconResource(showX, level));
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
index e77d1a2ccea1..44c920c7c0a7 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiStatusTracker.java
@@ -13,6 +13,7 @@ package com.android.settingslib.wifi;
import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_PARTIAL_CONNECTIVITY;
import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import android.content.Context;
import android.content.Intent;
@@ -247,6 +248,10 @@ public class WifiStatusTracker {
statusLabel = mContext.getString(R.string.wifi_status_no_internet);
}
return;
+ } else if (!isDefaultNetwork && mDefaultNetworkCapabilities != null
+ && mDefaultNetworkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ statusLabel = mContext.getString(R.string.wifi_connected_low_quality);
+ return;
}
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
index a654fd47ea12..8e850b25159c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/LocalMediaManagerTest.java
@@ -585,6 +585,7 @@ public class LocalMediaManagerTest {
when(device1.getId()).thenReturn(TEST_DEVICE_ID_1);
when(device2.getId()).thenReturn(TEST_DEVICE_ID_2);
when(device3.getId()).thenReturn(TEST_DEVICE_ID_3);
+ when(device1.getDeviceType()).thenReturn(MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE);
when(mLocalMediaManager.mPhoneDevice.getId()).thenReturn("test_phone_id");
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
@@ -683,6 +684,7 @@ public class LocalMediaManagerTest {
when(device1.getId()).thenReturn(TEST_DEVICE_ID_1);
when(device2.getId()).thenReturn(TEST_DEVICE_ID_2);
when(device3.getId()).thenReturn(TEST_DEVICE_ID_3);
+ when(device1.getDeviceType()).thenReturn(MediaDevice.MediaDeviceType.TYPE_PHONE_DEVICE);
when(mLocalMediaManager.mPhoneDevice.getId()).thenReturn("test_phone_id");
assertThat(mLocalMediaManager.mMediaDevices).hasSize(2);
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java
index 46e699d3bed5..c21830b28e3a 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/wifi/WifiEntryPreferenceTest.java
@@ -62,6 +62,17 @@ public class WifiEntryPreferenceTest {
@Mock
private Drawable mMockDrawable4;
+ @Mock
+ private Drawable mMockShowXDrawable0;
+ @Mock
+ private Drawable mMockShowXDrawable1;
+ @Mock
+ private Drawable mMockShowXDrawable2;
+ @Mock
+ private Drawable mMockShowXDrawable3;
+ @Mock
+ private Drawable mMockShowXDrawable4;
+
private static final String MOCK_TITLE = "title";
private static final String MOCK_SUMMARY = "summary";
private static final String FAKE_URI_STRING = "fakeuri";
@@ -75,11 +86,22 @@ public class WifiEntryPreferenceTest {
when(mMockWifiEntry.getTitle()).thenReturn(MOCK_TITLE);
when(mMockWifiEntry.getSummary(false /* concise */)).thenReturn(MOCK_SUMMARY);
- when(mMockIconInjector.getIcon(0)).thenReturn(mMockDrawable0);
- when(mMockIconInjector.getIcon(1)).thenReturn(mMockDrawable1);
- when(mMockIconInjector.getIcon(2)).thenReturn(mMockDrawable2);
- when(mMockIconInjector.getIcon(3)).thenReturn(mMockDrawable3);
- when(mMockIconInjector.getIcon(4)).thenReturn(mMockDrawable4);
+ when(mMockIconInjector.getIcon(false /* showX */, 0)).thenReturn(mMockDrawable0);
+ when(mMockIconInjector.getIcon(false /* showX */, 1)).thenReturn(mMockDrawable1);
+ when(mMockIconInjector.getIcon(false /* showX */, 2)).thenReturn(mMockDrawable2);
+ when(mMockIconInjector.getIcon(false /* showX */, 3)).thenReturn(mMockDrawable3);
+ when(mMockIconInjector.getIcon(false /* showX */, 4)).thenReturn(mMockDrawable4);
+
+ when(mMockIconInjector.getIcon(true /* showX */, 0))
+ .thenReturn(mMockShowXDrawable0);
+ when(mMockIconInjector.getIcon(true /* showX */, 1))
+ .thenReturn(mMockShowXDrawable1);
+ when(mMockIconInjector.getIcon(true /* showX */, 2))
+ .thenReturn(mMockShowXDrawable2);
+ when(mMockIconInjector.getIcon(true /* showX */, 3))
+ .thenReturn(mMockShowXDrawable3);
+ when(mMockIconInjector.getIcon(true /* showX */, 4))
+ .thenReturn(mMockShowXDrawable4);
}
@Test
@@ -155,6 +177,36 @@ public class WifiEntryPreferenceTest {
}
@Test
+ public void levelChanged_showXWifiRefresh_shouldUpdateLevelIcon() {
+ final List<Drawable> iconList = new ArrayList<>();
+ when(mMockWifiEntry.shouldShowXLevelIcon()).thenReturn(true);
+ final WifiEntryPreference pref =
+ new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
+
+ when(mMockWifiEntry.getLevel()).thenReturn(0);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(1);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(2);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(3);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(4);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+ when(mMockWifiEntry.getLevel()).thenReturn(-1);
+ pref.refresh();
+ iconList.add(pref.getIcon());
+
+ assertThat(iconList).containsExactly(mMockShowXDrawable0, mMockShowXDrawable1,
+ mMockShowXDrawable2, mMockShowXDrawable3, mMockShowXDrawable4, null);
+ }
+
+ @Test
public void notNull_whenGetHelpUriString_shouldSetImageButtonVisible() {
when(mMockWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING);
final WifiEntryPreference pref =
diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
index 0977799a6976..a311f0702a4b 100644
--- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
+++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java
@@ -165,8 +165,8 @@ public class SecureSettings {
Settings.Secure.AWARE_TAP_PAUSE_TOUCH_COUNT,
Settings.Secure.PEOPLE_STRIP,
Settings.Secure.MEDIA_CONTROLS_RESUME,
- Settings.Secure.MEDIA_CONTROLS_RESUME_BLOCKED,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
- Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS
+ Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS,
+ Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED
};
}
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
index c62fdc6a2780..9c5b60065118 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java
@@ -244,8 +244,6 @@ public class SecureSettingsValidators {
VALIDATORS.put(Secure.TAP_GESTURE, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.PEOPLE_STRIP, BOOLEAN_VALIDATOR);
VALIDATORS.put(Secure.MEDIA_CONTROLS_RESUME, BOOLEAN_VALIDATOR);
- VALIDATORS.put(Secure.MEDIA_CONTROLS_RESUME_BLOCKED,
- COLON_SEPARATED_PACKAGE_LIST_VALIDATOR);
VALIDATORS.put(Secure.ACCESSIBILITY_MAGNIFICATION_MODE,
new InclusiveIntegerRangeValidator(
Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN,
@@ -253,5 +251,6 @@ public class SecureSettingsValidators {
VALIDATORS.put(
Secure.ACCESSIBILITY_BUTTON_TARGETS,
ACCESSIBILITY_SHORTCUT_TARGET_LIST_VALIDATOR);
+ VALIDATORS.put(Secure.ADAPTIVE_CONNECTIVITY_ENABLED, BOOLEAN_VALIDATOR);
}
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index aae72e55b549..845c0a3847c1 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1979,6 +1979,9 @@ class SettingsProtoDumpUtil {
dumpSetting(s, p,
Settings.Secure.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS,
SecureSettingsProto.CONNECTIVITY_RELEASE_PENDING_INTENT_DELAY_MS);
+ dumpSetting(s, p,
+ Settings.Secure.ADAPTIVE_CONNECTIVITY_ENABLED,
+ SecureSettingsProto.ADAPTIVE_CONNECTIVITY_ENABLED);
final long controlsToken = p.start(SecureSettingsProto.CONTROLS);
dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/WriteFallbackSettingsFilesJobService.java b/packages/SettingsProvider/src/com/android/providers/settings/WriteFallbackSettingsFilesJobService.java
index 6e5b8890438d..66aa7baa3b51 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/WriteFallbackSettingsFilesJobService.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/WriteFallbackSettingsFilesJobService.java
@@ -35,19 +35,17 @@ import java.util.List;
public class WriteFallbackSettingsFilesJobService extends JobService {
@Override
public boolean onStartJob(final JobParameters params) {
- switch (params.getJobId()) {
- case WRITE_FALLBACK_SETTINGS_FILES_JOB_ID:
- final List<String> settingsFiles = new ArrayList<>();
- settingsFiles.add(params.getExtras().getString(TABLE_GLOBAL, ""));
- settingsFiles.add(params.getExtras().getString(TABLE_SYSTEM, ""));
- settingsFiles.add(params.getExtras().getString(TABLE_SECURE, ""));
- settingsFiles.add(params.getExtras().getString(TABLE_SSAID, ""));
- settingsFiles.add(params.getExtras().getString(TABLE_CONFIG, ""));
- SettingsProvider.writeFallBackSettingsFiles(settingsFiles);
- return true;
- default:
- return false;
+ if (params.getJobId() != WRITE_FALLBACK_SETTINGS_FILES_JOB_ID) {
+ return false;
}
+ final List<String> settingsFiles = new ArrayList<>();
+ settingsFiles.add(params.getExtras().getString(TABLE_GLOBAL, ""));
+ settingsFiles.add(params.getExtras().getString(TABLE_SYSTEM, ""));
+ settingsFiles.add(params.getExtras().getString(TABLE_SECURE, ""));
+ settingsFiles.add(params.getExtras().getString(TABLE_SSAID, ""));
+ settingsFiles.add(params.getExtras().getString(TABLE_CONFIG, ""));
+ SettingsProvider.writeFallBackSettingsFiles(settingsFiles);
+ return false;
}
@Override
diff --git a/packages/Shell/res/values-bn/strings.xml b/packages/Shell/res/values-bn/strings.xml
new file mode 100644
index 000000000000..ede125bce935
--- /dev/null
+++ b/packages/Shell/res/values-bn/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 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.
+ -->
+
+<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="3701846017049540910">"শেল"</string>
+ <string name="bugreport_notification_channel" msgid="2574150205913861141">"ত্রুটির প্রতিবেদন"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> তৈরি করা হচ্ছে"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> ক্যাপচার করা হয়েছে"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"ত্রুটির প্রতিবেদনে বিশদ বিবরণ যোগ করা হচ্ছে"</string>
+ <string name="bugreport_updating_wait" msgid="3322151947853929470">"অনুগ্রহ করে অপেক্ষা করুন..."</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"ফোনে শীঘ্রই ত্রুটির প্রতিবেদন দেখা যাবে"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"ত্রুটির প্রতিবেদনটি শেয়ার করতে এটি বেছে নিন"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"আপনার ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"কোনো স্ক্রিনশট ছাড়াই ত্রুটির প্রতিবেদনটি শেয়ার করতে এটি বেছে নিন, বা স্ক্রিনশটের জন্য অপেক্ষা করুন"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"কোনও স্ক্রিনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রিনশটের জন্য অপেক্ষা করুন"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"কোনও স্ক্রিনশট ছাড়াই ত্রুটির প্রতিবেদন শেয়ার করতে আলতো চাপ দিন বা সম্পন্ন করতে স্ক্রিনশটের জন্য অপেক্ষা করুন"</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"ত্রুটির প্রতিবেদনগুলিতে থাকা ডেটা, সিস্টেমের বিভিন্ন লগ ফাইলগুলি থেকে আসে, যাতে আপনার বিবেচনা অনুযায়ী সংবেদনশীল ডেটা (যেমন, অ্যাপ্লিকেশানের ব্যবহার এবং লোকেশন ডেটা) থাকতে পারে৷ আপনি বিশ্বাস করেন শুধুমাত্র এমন অ্যাপ্লিকেশান এবং ব্যক্তিদের সাথেই ত্রুটির প্রতিবেদনগুলিকে শেয়ার করুন৷"</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"আর দেখাবেন না"</string>
+ <string name="bugreport_storage_title" msgid="5332488144740527109">"ত্রুটির প্রতিবেদনগুলি"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"ত্রুটির প্রতিবেদনের ফাইলটি পড়া যায়নি"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"জিপ ফাইলে ত্রুটি প্রতিবেদনের বিশদ বিবরণ যোগ করা যায়নি"</string>
+ <string name="bugreport_unnamed" msgid="2800582406842092709">"নামবিহীন"</string>
+ <string name="bugreport_info_action" msgid="2158204228510576227">"বিশদ বিবরণ"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"স্ক্রিনশট নিন"</string>
+ <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"স্ক্রিনশট সফলভাবে নেওয়া হয়েছে৷"</string>
+ <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"স্ক্রিনশট নেওয়া যায়নি৷"</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ত্রুটির প্রতিবেদন <xliff:g id="ID">#%d</xliff:g> এর বিশদ বিবরণ"</string>
+ <string name="bugreport_info_name" msgid="4414036021935139527">"ফাইলের নাম"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ত্রুটির শীর্ষক"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ত্রুটির সারাংশ"</string>
+ <string name="save" msgid="4781509040564835759">"সেভ করুন"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"ত্রুটির প্রতিবেদন শেয়ার করুন"</string>
+</resources>
diff --git a/packages/Shell/res/values-eu/strings.xml b/packages/Shell/res/values-eu/strings.xml
new file mode 100644
index 000000000000..5d32cabd4ba5
--- /dev/null
+++ b/packages/Shell/res/values-eu/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 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.
+ -->
+
+<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="3701846017049540910">"Shell"</string>
+ <string name="bugreport_notification_channel" msgid="2574150205913861141">"Akatsen txostenak"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostena egiten ari gara"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostena egin da"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"Akatsen txostenean xehetasunak gehitzen"</string>
+ <string name="bugreport_updating_wait" msgid="3322151947853929470">"Itxaron, mesedez…"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Akatsen txostena telefonoan agertuko da laster"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Hautatu hau akatsen txostena partekatzeko"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Sakatu akatsen txostena partekatzeko"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Hautatu hau akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Sakatu akatsen txostena argazkirik gabe partekatzeko edo itxaron pantaila-argazkia atera arte"</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"Errore-txostenek sistemaren erregistro-fitxategietako datuak dauzkate, eta, haietan, kontuzkotzat jotzen duzun informazioa ager daiteke (adibidez, aplikazioen erabilera eta kokapen-datuak). Errore-txostenak partekatzen badituzu, partekatu soilik pertsona eta aplikazio fidagarriekin."</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Ez erakutsi berriro"</string>
+ <string name="bugreport_storage_title" msgid="5332488144740527109">"Akatsen txostenak"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"Ezin izan da irakurri akatsen txostena"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Ezin izan dira gehitu akatsen txostenaren xehetasunak ZIP fitxategian"</string>
+ <string name="bugreport_unnamed" msgid="2800582406842092709">"izengabea"</string>
+ <string name="bugreport_info_action" msgid="2158204228510576227">"Xehetasunak"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Pantaila-argazkia"</string>
+ <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"Atera da pantaila-argazkia."</string>
+ <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ezin izan da atera pantaila-argazkia."</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Akatsen <xliff:g id="ID">#%d</xliff:g> txostenaren xehetasunak"</string>
+ <string name="bugreport_info_name" msgid="4414036021935139527">"Fitxategi-izena"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Akatsaren izena"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Akatsaren laburpena"</string>
+ <string name="save" msgid="4781509040564835759">"Gorde"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Partekatu akatsen txostena"</string>
+</resources>
diff --git a/packages/Shell/res/values-gl/strings.xml b/packages/Shell/res/values-gl/strings.xml
new file mode 100644
index 000000000000..912dc85e15e4
--- /dev/null
+++ b/packages/Shell/res/values-gl/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 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.
+ -->
+
+<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="3701846017049540910">"Shell"</string>
+ <string name="bugreport_notification_channel" msgid="2574150205913861141">"Informes de erros"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Estase xerando o informe de erros <xliff:g id="ID">#%d</xliff:g>"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"Rexistrouse o informe de erros <xliff:g id="ID">#%d</xliff:g>"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"Engadindo detalles ao informe de erro"</string>
+ <string name="bugreport_updating_wait" msgid="3322151947853929470">"Agarda..."</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"O informe de erros aparecerá no teléfono en breve"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Selecciona para compartir o teu informe de erros"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Toca para compartir o teu informe de erros"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Selecciona para compartir o informe de erros sen captura de pantalla ou agarda a que acabe a captura"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Toca para compartir o informe de erros sen captura de pantalla ou agarda a que finalice a captura"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Toca para compartir o informe de erros sen captura de pantalla ou agarda a que finalice a captura"</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"Os informes de erros conteñen datos dos distintos ficheiros de rexistro do sistema, os cales poden incluír datos que consideres confidenciais (coma o uso de aplicacións e os datos de localización). Comparte os informes de erros só coas persoas e aplicacións nas que confíes."</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Non mostrar outra vez"</string>
+ <string name="bugreport_storage_title" msgid="5332488144740527109">"Informes de erros"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"Non se puido ler o ficheiro de informe de erros"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Non se puideron engadir os detalles do informe de erro ao ficheiro zip"</string>
+ <string name="bugreport_unnamed" msgid="2800582406842092709">"sen nome"</string>
+ <string name="bugreport_info_action" msgid="2158204228510576227">"Detalles"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Captura de pantalla"</string>
+ <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"A captura de pantalla realizouse correctamente."</string>
+ <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Non se puido realizar a captura de pantalla."</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Detalles do informe de erros <xliff:g id="ID">#%d</xliff:g>"</string>
+ <string name="bugreport_info_name" msgid="4414036021935139527">"Nome do ficheiro"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Título do informe de erros"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Resumo do informe de erros"</string>
+ <string name="save" msgid="4781509040564835759">"Gardar"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Compartir informe de erros"</string>
+</resources>
diff --git a/packages/Shell/res/values-is/strings.xml b/packages/Shell/res/values-is/strings.xml
new file mode 100644
index 000000000000..4989e8763b4d
--- /dev/null
+++ b/packages/Shell/res/values-is/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 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.
+ -->
+
+<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="3701846017049540910">"Skipanalína"</string>
+ <string name="bugreport_notification_channel" msgid="2574150205913861141">"Villutilkynningar"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Verið er að búa til villutilkynningu <xliff:g id="ID">#%d</xliff:g>"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"Villutilkynning <xliff:g id="ID">#%d</xliff:g> búin til"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"Bætir upplýsingum við villutilkynningu"</string>
+ <string name="bugreport_updating_wait" msgid="3322151947853929470">"Augnablik..."</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Villuskýrslan birtist brátt í símanum"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Veldu að deila villutilkynningunni"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Ýttu til að deila villutilkynningunni"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Veldu að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Ýttu til að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Ýttu til að deila villutilkynningunni án skjámyndar eða hinkraðu þangað til skjámyndin er tilbúin"</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"Villutilkynningar innihalda gögn úr ýmsum annálaskrám kerfisins sem gætu innihaldið upplýsingar sem þú telur viðkvæmar (til dæmis notkun forrita og staðsetningarupplýsingar). Deildu villutilkynningum bara með fólki og forritum sem þú treystir."</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Ekki sýna þetta aftur"</string>
+ <string name="bugreport_storage_title" msgid="5332488144740527109">"Villutilkynningar"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"Ekki var hægt að lesa úr villuskýrslunni"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Ekki tókst að bæta upplýsingum um villutilkynningu við ZIP-skrá"</string>
+ <string name="bugreport_unnamed" msgid="2800582406842092709">"án heitis"</string>
+ <string name="bugreport_info_action" msgid="2158204228510576227">"Nánar"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Skjámynd"</string>
+ <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"Skjámynd tekin."</string>
+ <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Ekki tókst að taka skjámynd."</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Upplýsingar villutilkynningar <xliff:g id="ID">#%d</xliff:g>"</string>
+ <string name="bugreport_info_name" msgid="4414036021935139527">"Skráarheiti"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Heiti villu"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Villusamantekt"</string>
+ <string name="save" msgid="4781509040564835759">"Vista"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Deila villutilkynningu"</string>
+</resources>
diff --git a/packages/Shell/res/values-ky/strings.xml b/packages/Shell/res/values-ky/strings.xml
new file mode 100644
index 000000000000..3567ac276e63
--- /dev/null
+++ b/packages/Shell/res/values-ky/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 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.
+ -->
+
+<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="3701846017049540910">"Кабык"</string>
+ <string name="bugreport_notification_channel" msgid="2574150205913861141">"Мүчүлүштүк тууралуу кабар берүүлөр"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Мүчүлүштүк тууралуу билдирүү <xliff:g id="ID">#%d</xliff:g> түзүлүүдө"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"Мүчүлүштүк тууралуу билдирүү <xliff:g id="ID">#%d</xliff:g> жаздырылды"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"Мүчүлүштүк жөнүндө кабардын чоо-жайы кошулууда"</string>
+ <string name="bugreport_updating_wait" msgid="3322151947853929470">"Күтө туруңуз…"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Мүчүлүштүктөр жөнүндө кабар жакында телефонго чыгат"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Мүчүлүштүк тууралуу кабарды жөнөтүү үчүн таптап коюңуз"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Мүчүлүштүк тууралуу билдирүүңүздү бөлүшүү үчүн таптап коюңуз"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Мүчүлүштүк тууралуу кабарды скриншотсуз жөнөтүү үчүн солго серпиңиз же скриншот даяр болгуча күтүңүз"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Мүчүлүштүк тууралуу билдирүүңүздү скриншотсуз бөлүшүү үчүн таптап коюңуз же скриншот даяр болгуча күтө туруңуз"</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"Мүчүлүштүктөр тууралуу билдирүүлөрдө тутумдун ар кандай таржымалдарынан алынган дайындар, ошондой эле купуя маалымат камтылышы мүмкүн (мисалы, жайгашкан жер сыяктуу). Мындай билдирүүлөрдү бир гана ишеничтүү адамдар жана колдонмолор менен бөлүшүңүз."</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Экинчи көрүнбөсүн"</string>
+ <string name="bugreport_storage_title" msgid="5332488144740527109">"Мүчүлүштүктөрдү кабарлоо"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"Мүчүлүштүк тууралуу кабарлаган файл окулбай койду"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Мүчүлүштүктөр жөнүндө кабардын чоо-жайы zip файлына кошулбай койду"</string>
+ <string name="bugreport_unnamed" msgid="2800582406842092709">"аталышы жок"</string>
+ <string name="bugreport_info_action" msgid="2158204228510576227">"Чоо-жайы"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Скриншот"</string>
+ <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"Скриншот ийгиликтүү тартылды."</string>
+ <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Скриншот тартылбай койду."</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Мүчүлүштүк тууралуу билдирүүнүн <xliff:g id="ID">#%d</xliff:g> чоо-жайы"</string>
+ <string name="bugreport_info_name" msgid="4414036021935139527">"Файлдын аталышы"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Мүчүлүштүктүн аталышы"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Мүчүлүштүк корутундусу"</string>
+ <string name="save" msgid="4781509040564835759">"Сактоо"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Мүчүлүштүк тууралуу кабарлоо"</string>
+</resources>
diff --git a/packages/Shell/res/values-mk/strings.xml b/packages/Shell/res/values-mk/strings.xml
new file mode 100644
index 000000000000..3d18d30715c2
--- /dev/null
+++ b/packages/Shell/res/values-mk/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 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.
+ -->
+
+<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="3701846017049540910">"Shell"</string>
+ <string name="bugreport_notification_channel" msgid="2574150205913861141">"Извештаи за грешки"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"Се генерира извештајот за грешки <xliff:g id="ID">#%d</xliff:g>"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"Извештајот за грешки <xliff:g id="ID">#%d</xliff:g> е снимен"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"Се додаваат детали на извештајот за грешка"</string>
+ <string name="bugreport_updating_wait" msgid="3322151947853929470">"Почекајте..."</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"Извештајот за грешки наскоро ќе се појави на телефонот"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"Изберете да го споделите извештајот за грешки"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"Допрете за да го споделите извештајот за грешки"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"Изберете да го спод. извештајот за грешки без слика од екранот или почекајте да се подготви сликата"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"Допрете за споделување извештај за грешки без слика од екранот или почекајте да се подготви сликата"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"Допрете за споделување извештај за грешки без слика од екранот или почекајте да се подготви сликата"</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"Извештаите за грешка содржат податоци од разни датотеки за евиденција на системот, вклучувајќи и податоци што можеби ги сметате за чувствителни (како што се користење на апликациите и податоци за локацијата). Извештаите за грешки споделувајте ги само со апликации и луѓе во кои имате доверба."</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"Не покажувај повторно"</string>
+ <string name="bugreport_storage_title" msgid="5332488144740527109">"Извештаи за грешки"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"Датотеката со извештај за грешка не можеше да се прочита"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"Не можевме да ги додадеме деталите на извештајот за грешки во zip-датотеката"</string>
+ <string name="bugreport_unnamed" msgid="2800582406842092709">"неименувани"</string>
+ <string name="bugreport_info_action" msgid="2158204228510576227">"Детали"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"Слика од екранот"</string>
+ <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"Успешно е направена слика од екранот."</string>
+ <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"Не може да се направи слика од екранот."</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"Детали за извештајот за грешки <xliff:g id="ID">#%d</xliff:g>"</string>
+ <string name="bugreport_info_name" msgid="4414036021935139527">"Име на датотека"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"Наслов на грешката"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"Преглед на грешката"</string>
+ <string name="save" msgid="4781509040564835759">"Зачувај"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"Споделете извештај за грешки"</string>
+</resources>
diff --git a/packages/Shell/res/values-ml/strings.xml b/packages/Shell/res/values-ml/strings.xml
new file mode 100644
index 000000000000..78b43bbe3d7b
--- /dev/null
+++ b/packages/Shell/res/values-ml/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 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.
+ -->
+
+<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="3701846017049540910">"ഷെൽ"</string>
+ <string name="bugreport_notification_channel" msgid="2574150205913861141">"ബഗ് റിപ്പോർട്ടുകൾ"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> സൃഷ്ടിക്കുന്നു"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> ക്യാപ്ചർ ചെയ്തു"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"ബഗ് റിപ്പോർട്ടിലേക്ക് വിശദാംശങ്ങൾ ചേർക്കുന്നു"</string>
+ <string name="bugreport_updating_wait" msgid="3322151947853929470">"കാത്തിരിക്കുക..."</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"ബഗ് റിപ്പോർട്ട് താമസിയാതെ ഫോണിൽ ദൃശ്യമാകും"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടുന്നതിന് തിരഞ്ഞെടുക്കുക"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ ബഗ് റിപ്പോർട്ട് പങ്കിടുക"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"സ്ക്രീൻഷോട്ട് കൂടാതെയോ സ്ക്രീൻഷോട്ട് പൂർത്തിയാകുന്നതിന് കാക്കാതെയോ നിങ്ങളുടെ ബഗ് റിപ്പോർട്ട് പങ്കിടാൻ ടാപ്പുചെയ്യുക"</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"ബഗ് റിപ്പോർട്ടുകളിൽ സിസ്റ്റത്തിന്റെ നിരവധി ലോഗ് ഫയലുകളിൽ നിന്നുള്ള വിവരങ്ങൾ അടങ്ങിയിരിക്കുന്നു, ഇതിൽ നിങ്ങൾ രഹസ്യ സ്വഭാവമുള്ളവയായി പരിഗണിക്കുന്ന വിവരങ്ങളും (ആപ്പ് ഉപയോഗ വിവരങ്ങൾ, ലൊക്കേഷൻ വിവരങ്ങൾ എന്നിവ പോലെ) ഉൾപ്പെടാം. നിങ്ങൾ വിശ്വസിക്കുന്ന ആപ്പുകൾക്കും ആളുകൾക്കും മാത്രം ബഗ് റിപ്പോർട്ടുകൾ പങ്കിടുക."</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"വീണ്ടും കാണിക്കരുത്"</string>
+ <string name="bugreport_storage_title" msgid="5332488144740527109">"ബഗ് റിപ്പോർട്ടുകൾ"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"ബഗ് റിപ്പോർട്ട് ഫയൽ വായിക്കാനായില്ല"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"സിപ്പ് ഫയലിലേക്ക് ബഗ് റിപ്പോർട്ട് വിശദാംശങ്ങൾ ചേർക്കാൻ കഴിഞ്ഞില്ല"</string>
+ <string name="bugreport_unnamed" msgid="2800582406842092709">"പേരില്ലാത്തവർ"</string>
+ <string name="bugreport_info_action" msgid="2158204228510576227">"വിശദാംശങ്ങൾ"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"സ്‌ക്രീൻഷോട്ട്"</string>
+ <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"സ്ക്രീൻഷോട്ട് എടുത്തു."</string>
+ <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"സ്ക്രീൻഷോട്ട് എടുക്കാൻ കഴിഞ്ഞില്ല."</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ബഗ് റിപ്പോർട്ട് <xliff:g id="ID">#%d</xliff:g> വിശദാംശങ്ങൾ"</string>
+ <string name="bugreport_info_name" msgid="4414036021935139527">"ഫയല്‍നാമം"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ബഗിന്റെ പേര്"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ബഗ് സംഗ്രഹം"</string>
+ <string name="save" msgid="4781509040564835759">"സംരക്ഷിക്കുക"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"ബഗ് റിപ്പോർട്ട് പങ്കിടുക"</string>
+</resources>
diff --git a/packages/Shell/res/values-mr/strings.xml b/packages/Shell/res/values-mr/strings.xml
new file mode 100644
index 000000000000..9595e28eb6e2
--- /dev/null
+++ b/packages/Shell/res/values-mr/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 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.
+ -->
+
+<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="3701846017049540910">"शेल"</string>
+ <string name="bugreport_notification_channel" msgid="2574150205913861141">"बग रीपोर्ट"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"बग रीपोर्ट <xliff:g id="ID">#%d</xliff:g> तयार केला जात आहे"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"बग रीपोर्ट <xliff:g id="ID">#%d</xliff:g> कॅप्चर केला"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"दोष अहवालामध्‍ये तपशील जोडत आहे"</string>
+ <string name="bugreport_updating_wait" msgid="3322151947853929470">"कृपया प्रतीक्षा करा..."</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"फोनवर बग रीपोर्ट लवकरच दिसेल"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"तुमचा बग रीपोर्ट शेअर करण्यासाठी निवडा"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"तुमचा बग रीपोर्ट शेअर करण्यासाठी टॅप करा"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"तुमचा बग रीपोर्ट स्क्रीनशॉटशिवाय शेअर करण्यासाठी टॅप करा किंवा स्क्रीनशॉट पूर्ण होण्याची प्रतीक्षा करा"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"स्क्रीनशॉट शिवाय तुमचा बग रीपोर्ट शेअर करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"स्क्रीनशॉट शिवाय तुमचा बग रीपोर्ट शेअर करण्यासाठी टॅप करा किंवा समाप्त करण्यासाठी स्क्रीनशॉटची प्रतीक्षा करा"</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"बग रीपोर्टांमध्ये तुम्ही संवेदनशील (अ‍ॅप-वापर आणि स्थान डेटा यासारखा) डेटा म्हणून विचार करता त्या डेटाच्या समावेशासह सिस्टीमच्या विविध लॉग फायलींमधील डेटा असतो. ज्या लोकांवर आणि अ‍ॅपवर तुमचा विश्वास आहे केवळ त्यांच्यासह हा बग रीपोर्ट शेअर करा."</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"पुन्हा दर्शवू नका"</string>
+ <string name="bugreport_storage_title" msgid="5332488144740527109">"बग रीपोर्ट"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"बग रीपोर्ट फाईल वाचणे शक्य झाले नाही"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"झिप फाईल मध्ये बग रीपोर्ट तपशील जोडणे शक्य झाले नाही"</string>
+ <string name="bugreport_unnamed" msgid="2800582406842092709">"अनामित"</string>
+ <string name="bugreport_info_action" msgid="2158204228510576227">"तपशील"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"स्क्रीनशॉट"</string>
+ <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"स्क्रीनशॉट यशस्वीरित्या घेतला."</string>
+ <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"स्क्रीनशॉट घेणे शक्य झाले नाही."</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"बग रीपोर्ट <xliff:g id="ID">#%d</xliff:g> तपशील"</string>
+ <string name="bugreport_info_name" msgid="4414036021935139527">"फाईलनाव"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"दोष शीर्षक"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"दोष सारांश"</string>
+ <string name="save" msgid="4781509040564835759">"सेव्ह करा"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"बग रीपोर्ट शेअर करा"</string>
+</resources>
diff --git a/packages/Shell/res/values-my/strings.xml b/packages/Shell/res/values-my/strings.xml
new file mode 100644
index 000000000000..2376ffd2b2cf
--- /dev/null
+++ b/packages/Shell/res/values-my/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 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.
+ -->
+
+<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="3701846017049540910">"အခွံ"</string>
+ <string name="bugreport_notification_channel" msgid="2574150205913861141">"ချွတ်ယွင်းမှု အစီရင်ခံစာများ"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> ကိုထုတ်နေပါသည်"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> ကိုရယူထားပြီးပါပြီ"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"ချွတ်ယွင်းချက်အစီရင်ခံချက်သို့ အသေးစိတ်များပေါင်းထည့်ရန်"</string>
+ <string name="bugreport_updating_wait" msgid="3322151947853929470">"ခေတ္တစောင့်ပါ..."</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"ချွတ်ယွင်းချက်အစီရင်ခံစာကို မကြာခင် ဖုန်းထဲတွင် မြင်တွေ့ရပါလိမ့်မည်"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"ချွတ်ယွင်းချက်အစီရင်ခံစာကို မျှဝေရန် ရွေးချယ်ပါ"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"သင့်ချွတ်ယွင်းမှုအစီရင်ခံချက်ကို မျှဝေရန် တို့ပါ"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"ချွတ်ယွင်းမှုအစီရင်ခံစာကို ဖန်သားပြင်ပုံ မပါဘဲမျှဝေပါ (သို့) ဖန်သားပြင်ပုံ ရိုက်ပြီးသည်အထိ စောင့်ပါ"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ချွတ်ယွင်းချက်အစီရင်ခံစာကို ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းမပါဘဲ မျှဝေရန် တို့ပါ သို့မဟုတ် ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ချွတ်ယွင်းချက်အစီရင်ခံစာကို ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းမပါဘဲ မျှဝေရန် တို့ပါ သို့မဟုတ် ဖန်သားပြင်ဓာတ်ပုံမှတ်တမ်းတင်ခြင်း ပြီးဆုံးသည်အထိ စောင့်ပါ"</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"ချွတ်ယွင်းချက်အစီရင်ခံစာများတွင် သင့်အတွက် အရေးကြီးသည့် ဒေတာများ (အက်ပ်အသုံးပြုမှုနှင့် တည်နေရာအချက်အလက် ကဲ့သို့) ပါဝင်သည့် စနစ်၏မှတ်တမ်းဖိုင်မျိုးစုံပါဝင်ပါသည်။ ချွတ်ယွင်းချက်အစီရင်ခံစာများကို သင်ယုံကြည်စိတ်ချရသည့်လူများ၊ အက်ပ်များနှင့်သာ မျှဝေပါ။"</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"နောက်ထပ်မပြပါနှင့်"</string>
+ <string name="bugreport_storage_title" msgid="5332488144740527109">"ချွတ်ယွင်းမှု အစီရင်ခံစာများ"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"ချွတ်ယွင်းချက် အစီရင်ခံစာကို ဖတ်၍မရပါ"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"ဇစ်ဖိုင်သို့ ချွတ်ယွင်းချက် အစီရင်ခံစာအသေးစိတ် အချက်အလက်များကို ထည့်၍မရပါ"</string>
+ <string name="bugreport_unnamed" msgid="2800582406842092709">"အမည်မဲ့"</string>
+ <string name="bugreport_info_action" msgid="2158204228510576227">"အသေးစိတ်များ"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"မျက်နှာပြင် လျှပ်တစ်ပြက်ပုံ"</string>
+ <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"ဖန်သားပြင်ဓာတ်ပုံ အောင်မြင်စွာရိုက်ပြီးပါပြီ။"</string>
+ <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"မျက်နှာပြင် လျှပ်တစ်ပြက်ပုံ မရိုက်နိုင်ပါ"</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"ချွတ်ယွင်းမှုအစီရင်ခံချက် <xliff:g id="ID">#%d</xliff:g> အသေးစိတ်များ"</string>
+ <string name="bugreport_info_name" msgid="4414036021935139527">"ဖိုင်အမည်"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"ချွတ်ယွင်းချက် ခေါင်းစဉ်"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"ချွတ်ယွင်းချက် အကျဉ်းချုပ်"</string>
+ <string name="save" msgid="4781509040564835759">"သိမ်းရန်"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"ချွတ်ယွင်းချက်မှတ်တမ်း မျှဝေပါ"</string>
+</resources>
diff --git a/packages/Shell/res/values-ta/strings.xml b/packages/Shell/res/values-ta/strings.xml
new file mode 100644
index 000000000000..a906abede3fd
--- /dev/null
+++ b/packages/Shell/res/values-ta/strings.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2013 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.
+ -->
+
+<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="3701846017049540910">"ஷெல்"</string>
+ <string name="bugreport_notification_channel" msgid="2574150205913861141">"பிழை அறிக்கைகள்"</string>
+ <string name="bugreport_in_progress_title" msgid="4311705936714972757">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> உருவாக்கப்படுகிறது"</string>
+ <string name="bugreport_finished_title" msgid="4429132808670114081">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> எடுக்கப்பட்டது"</string>
+ <string name="bugreport_updating_title" msgid="4423539949559634214">"பிழை அறிக்கையில் விவரங்களைச் சேர்க்கிறது"</string>
+ <string name="bugreport_updating_wait" msgid="3322151947853929470">"காத்திருக்கவும்…"</string>
+ <string name="bugreport_finished_text" product="watch" msgid="1223616207145252689">"பிழை அறிக்கை சிறிது நேரத்தில் மொபைலில் தோன்றும்"</string>
+ <string name="bugreport_finished_text" product="tv" msgid="5758325479058638893">"பிழை அறிக்கையைப் பகிர, தேர்ந்தெடுக்கவும்"</string>
+ <string name="bugreport_finished_text" product="default" msgid="8353769438382138847">"பிழை அறிக்கையைப் பகிர, தட்டவும்"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="tv" msgid="2343263822812016950">"ஸ்கிரீன்ஷாட் இன்றி பிழை அறிக்கையை பகிர தேர்ந்தெடுக்கவும்/ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="watch" msgid="1474435374470177193">"ஸ்கிரீன்ஷாட் இல்லாமல் பிழை அறிக்கையைப் பகிர, தட்டவும் அல்லது ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்"</string>
+ <string name="bugreport_finished_pending_screenshot_text" product="default" msgid="1474435374470177193">"ஸ்கிரீன்ஷாட் இல்லாமல் பிழை அறிக்கையைப் பகிர, தட்டவும் அல்லது ஸ்கிரீன்ஷாட் முடியும்வரை காத்திருக்கவும்"</string>
+ <string name="bugreport_confirm" msgid="5917407234515812495">"பிழை அறிக்கைகளில் முறைமையின் பல்வேறு பதிவுக் கோப்புகளின் தரவு (இதில் முக்கியமானவை என நீங்கள் கருதும் பயன்பாடின் உபயோகம், இருப்பிடத் தரவு போன்றவை அடங்கும்) இருக்கும். நீங்கள் நம்பும் நபர்கள் மற்றும் பயன்பாடுகளுடன் மட்டும் பிழை அறிக்கைகளைப் பகிரவும்."</string>
+ <string name="bugreport_confirm_dont_repeat" msgid="6179945398364357318">"மீண்டும் காட்டாதே"</string>
+ <string name="bugreport_storage_title" msgid="5332488144740527109">"பிழை அறிக்கைகள்"</string>
+ <string name="bugreport_unreadable_text" msgid="586517851044535486">"பிழை அறிக்கையைப் படிக்க முடியவில்லை"</string>
+ <string name="bugreport_add_details_to_zip_failed" msgid="1302931926486712371">"பிழை அறிக்கை விவரங்களை ஜிப் கோப்பில் சேர்க்க முடியவில்லை"</string>
+ <string name="bugreport_unnamed" msgid="2800582406842092709">"பெயரிடப்படாதது"</string>
+ <string name="bugreport_info_action" msgid="2158204228510576227">"விவரங்கள்"</string>
+ <string name="bugreport_screenshot_action" msgid="8677781721940614995">"ஸ்கிரீன்ஷாட்"</string>
+ <string name="bugreport_screenshot_taken" msgid="5684211273096253120">"ஸ்கிரீன்ஷாட் எடுக்கப்பட்டது."</string>
+ <string name="bugreport_screenshot_failed" msgid="5853049140806834601">"ஸ்கிரீன் ஷாட்டை எடுக்க முடியவில்லை."</string>
+ <string name="bugreport_info_dialog_title" msgid="1355948594292983332">"பிழை அறிக்கை <xliff:g id="ID">#%d</xliff:g> இன் விவரங்கள்"</string>
+ <string name="bugreport_info_name" msgid="4414036021935139527">"கோப்புப்பெயர்"</string>
+ <string name="bugreport_info_title" msgid="2306030793918239804">"பிழை தலைப்பு"</string>
+ <string name="bugreport_info_description" msgid="5072835127481627722">"பிழை குறித்த சுருக்க விவரம்"</string>
+ <string name="save" msgid="4781509040564835759">"சேமி"</string>
+ <string name="bugreport_intent_chooser_title" msgid="7605709494790894076">"பிழை அறிக்கையைப் பகிர்"</string>
+</resources>
diff --git a/packages/SoundPicker/res/values-ar/strings.xml b/packages/SoundPicker/res/values-ar/strings.xml
index a91795545269..f8844e94815f 100644
--- a/packages/SoundPicker/res/values-ar/strings.xml
+++ b/packages/SoundPicker/res/values-ar/strings.xml
@@ -25,5 +25,5 @@
<string name="delete_ringtone_text" msgid="201443984070732499">"حذف"</string>
<string name="unable_to_add_ringtone" msgid="4583511263449467326">"يتعذر إضافة نغمة رنين مخصصة"</string>
<string name="unable_to_delete_ringtone" msgid="6792301380142859496">"يتعذر حذف نغمة الرنين المخصصة"</string>
- <string name="app_label" msgid="3091611356093417332">"Sounds"</string>
+ <string name="app_label" msgid="3091611356093417332">"الأصوات"</string>
</resources>
diff --git a/packages/SoundPicker/res/values-cs/strings.xml b/packages/SoundPicker/res/values-cs/strings.xml
index e8fc97e44174..dc67c960cca9 100644
--- a/packages/SoundPicker/res/values-cs/strings.xml
+++ b/packages/SoundPicker/res/values-cs/strings.xml
@@ -16,14 +16,14 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="ringtone_default" msgid="798836092118824500">"Výchozí vyzváněcí tón"</string>
+ <string name="ringtone_default" msgid="798836092118824500">"Výchozí vyzvánění"</string>
<string name="notification_sound_default" msgid="8133121186242636840">"Výchozí zvuk oznámení"</string>
<string name="alarm_sound_default" msgid="4787646764557462649">"Výchozí zvuk budíku"</string>
- <string name="add_ringtone_text" msgid="6642389991738337529">"Přidat vyzváněcí tón"</string>
+ <string name="add_ringtone_text" msgid="6642389991738337529">"Přidat vyzvánění"</string>
<string name="add_alarm_text" msgid="3545497316166999225">"Přidat budík"</string>
<string name="add_notification_text" msgid="4431129543300614788">"Přidat oznámení"</string>
<string name="delete_ringtone_text" msgid="201443984070732499">"Smazat"</string>
- <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Vlastní vyzváněcí tón se nepodařilo přidat"</string>
- <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Vlastní vyzváněcí tón se nepodařilo smazat"</string>
+ <string name="unable_to_add_ringtone" msgid="4583511263449467326">"Vlastní vyzvánění se nepodařilo přidat"</string>
+ <string name="unable_to_delete_ringtone" msgid="6792301380142859496">"Vlastní vyzvánění se nepodařilo smazat"</string>
<string name="app_label" msgid="3091611356093417332">"Zvuky"</string>
</resources>
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 7b8aba451e27..b55854131709 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -720,10 +720,9 @@
<service android:name=".controls.controller.AuxiliaryPersistenceWrapper$DeletionJobService"
android:permission="android.permission.BIND_JOB_SERVICE"/>
- <!-- started from ControlsFavoritingActivity -->
+ <!-- started from ControlsRequestReceiver -->
<activity
android:name=".controls.management.ControlsRequestDialog"
- android:exported="true"
android:theme="@style/Theme.ControlsRequestDialog"
android:finishOnCloseSystemDialogs="true"
android:showForAllUsers="true"
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
index 7463d3fd3650..8f24e7927e3a 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
@@ -75,6 +75,11 @@ public interface NotificationMenuRowPlugin extends Plugin {
public MenuItem getLongpressMenuItem(Context context);
/**
+ * @return the {@link MenuItem} to display when app ops icons are pressed.
+ */
+ public MenuItem getAppOpsMenuItem(Context context);
+
+ /**
* @return the {@link MenuItem} to display when snooze item is pressed.
*/
public MenuItem getSnoozeMenuItem(Context context);
diff --git a/packages/SystemUI/res-keyguard/values-ar/strings.xml b/packages/SystemUI/res-keyguard/values-ar/strings.xml
index 6d86a78360d8..65e3f0dbd176 100644
--- a/packages/SystemUI/res-keyguard/values-ar/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-ar/strings.xml
@@ -112,7 +112,7 @@
<string name="kg_pin_accepted" msgid="1625501841604389716">"تم قبول الرمز"</string>
<string name="keyguard_carrier_default" msgid="6359808469637388586">"لا تتوفر خدمة."</string>
<string name="accessibility_ime_switch_button" msgid="9082358310194861329">"تبديل أسلوب الإدخال"</string>
- <string name="airplane_mode" msgid="2528005343938497866">"وضع الطائرة"</string>
+ <string name="airplane_mode" msgid="2528005343938497866">"وضع الطيران"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="4720554342633852066">"يجب رسم النقش بعد إعادة تشغيل الجهاز"</string>
<string name="kg_prompt_reason_restart_pin" msgid="1587671566498057656">"يجب إدخال رقم التعريف الشخصي بعد إعادة تشغيل الجهاز"</string>
<string name="kg_prompt_reason_restart_password" msgid="8061279087240952002">"يجب إدخال كلمة المرور بعد إعادة تشغيل الجهاز"</string>
diff --git a/packages/SystemUI/res-keyguard/values-te/strings.xml b/packages/SystemUI/res-keyguard/values-te/strings.xml
index 74386bc7a487..d44003bc5b95 100644
--- a/packages/SystemUI/res-keyguard/values-te/strings.xml
+++ b/packages/SystemUI/res-keyguard/values-te/strings.xml
@@ -134,7 +134,7 @@
<item quantity="other">SIM ఇప్పుడు నిలిపివేయబడింది. PUK కోడ్‌ను నమోదు చేయండి. SIM శాశ్వతంగా నిరుపయోగం కాకుండా ఉండటానికి మీకు <xliff:g id="_NUMBER_1">%d</xliff:g> ప్రయత్నాలు మిగిలి ఉన్నాయి. వివరాల కోసం కారియర్‌ను సంప్రదించండి.</item>
<item quantity="one">SIM ఇప్పుడు నిలిపివేయబడింది. PUK కోడ్‌ను నమోదు చేయండి. SIM శాశ్వతంగా నిరుపయోగం కాకుండా ఉండటానికి మీకు <xliff:g id="_NUMBER_0">%d</xliff:g> ప్రయత్నం మిగిలి ఉంది వివరాల కోసం కారియర్‌ను సంప్రదించండి.</item>
</plurals>
- <string name="clock_title_default" msgid="6342735240617459864">"డిఫాల్ట్"</string>
+ <string name="clock_title_default" msgid="6342735240617459864">"ఆటోమేటిక్"</string>
<string name="clock_title_bubble" msgid="2204559396790593213">"బబుల్"</string>
<string name="clock_title_analog" msgid="8409262532900918273">"ఎనలాగ్"</string>
</resources>
diff --git a/packages/SystemUI/res-product/values-in/strings.xml b/packages/SystemUI/res-product/values-in/strings.xml
index 2e0580f568f9..1451e2c063c9 100644
--- a/packages/SystemUI/res-product/values-in/strings.xml
+++ b/packages/SystemUI/res-product/values-in/strings.xml
@@ -26,10 +26,10 @@
<string name="keyguard_missing_sim_message" product="tablet" msgid="5018086454277963787">"Tidak ada kartu SIM dalam tablet."</string>
<string name="keyguard_missing_sim_message" product="default" msgid="7053347843877341391">"Tidak ada kartu SIM dalam ponsel."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="6278551068943958651">"Kode PIN tidak cocok"</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, tablet ini akan disetel ulang, sehingga semua datanya akan dihapus."</string>
- <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, ponsel ini akan disetel ulang, sehingga semua datanya akan dihapus."</string>
- <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Tablet ini akan disetel ulang, sehingga semua datanya akan dihapus."</string>
- <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Ponsel ini akan disetel ulang, sehingga semua datanya akan dihapus."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="302165994845009232">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, tablet ini akan direset, sehingga semua datanya akan dihapus."</string>
+ <string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="2594813176164266847">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, ponsel ini akan direset, sehingga semua datanya akan dihapus."</string>
+ <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="8710104080409538587">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Tablet ini akan direset, sehingga semua datanya akan dihapus."</string>
+ <string name="kg_failed_attempts_now_wiping" product="default" msgid="6381835450014881813">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Ponsel ini akan direset, sehingga semua datanya akan dihapus."</string>
<string name="kg_failed_attempts_almost_at_erase_user" product="tablet" msgid="7325071812832605911">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, pengguna ini akan dihapus, sehingga semua data pengguna akan dihapus."</string>
<string name="kg_failed_attempts_almost_at_erase_user" product="default" msgid="8110939900089863103">"Anda telah <xliff:g id="NUMBER_0">%1$d</xliff:g> kali berupaya membuka kunci ponsel dengan tidak benar. Setelah <xliff:g id="NUMBER_1">%2$d</xliff:g> lagi upaya yang tidak berhasil, pengguna ini akan dihapus, sehingga semua data pengguna akan dihapus."</string>
<string name="kg_failed_attempts_now_erasing_user" product="tablet" msgid="8509811676952707883">"Anda telah <xliff:g id="NUMBER">%d</xliff:g> kali berupaya membuka kunci tablet dengan tidak benar. Pengguna ini akan dihapus, sehingga semua data pengguna akan dihapus."</string>
diff --git a/packages/SystemUI/res/drawable-mcc310-mnc004/ic_5g_plus_mobiledata.xml b/packages/SystemUI/res/drawable-mcc310-mnc004/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..998db3b44b19
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mcc310-mnc004/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,36 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
+
diff --git a/packages/SystemUI/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml b/packages/SystemUI/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml
new file mode 100644
index 000000000000..998db3b44b19
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mcc311-mnc480/ic_5g_plus_mobiledata.xml
@@ -0,0 +1,36 @@
+<!--
+ 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:viewportWidth="22"
+ android:viewportHeight="17"
+ android:width="22dp"
+ android:height="17dp">
+ <group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.98,3.54v2.81c0,0.47 -0.15,0.84 -0.44,1.11s-0.69,0.41 -1.2,0.41c-0.5,0 -0.89,-0.13 -1.19,-0.4s-0.44,-0.63 -0.45,-1.09V3.54h0.88v2.82c0,0.28 0.07,0.48 0.2,0.61c0.13,0.13 0.32,0.19 0.56,0.19c0.49,0 0.75,-0.26 0.75,-0.78V3.54H19.98z"/>
+ <path android:fillColor="#FF000000"
+ android:pathData="M19.42,12.25l0.57,-3.04h0.88l-0.95,4.27h-0.88l-0.69,-2.85l-0.69,2.85h-0.88l-0.95,-4.27h0.88l0.58,3.03l0.7,-3.03h0.74L19.42,12.25z"/>
+ </group>
+ <group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M0.94,8.49l0.43,-4.96H5.7v1.17H2.39L2.15,7.41c0.41,-0.29 0.85,-0.43 1.33,-0.43c0.77,0 1.38,0.3 1.83,0.9c0.44,0.6 0.66,1.41 0.66,2.43c0,1.03 -0.24,1.84 -0.72,2.43c-0.48,0.59 -1.14,0.88 -1.98,0.88c-0.75,0 -1.36,-0.24 -1.83,-0.73c-0.47,-0.49 -0.74,-1.16 -0.81,-2.02h1.13c0.07,0.57 0.23,1 0.49,1.29c0.26,0.29 0.59,0.43 1.01,0.43c0.47,0 0.84,-0.2 1.1,-0.61c0.26,-0.41 0.4,-0.96 0.4,-1.65c0,-0.65 -0.14,-1.18 -0.43,-1.59C4.05,8.32 3.67,8.11 3.19,8.11c-0.4,0 -0.72,0.1 -0.96,0.31L1.9,8.75L0.94,8.49z"/>
+ </group>
+ <path android:fillColor="#FF000000"
+ android:pathData="M13.86,12.24l-0.22,0.27c-0.63,0.73 -1.55,1.1 -2.76,1.1c-1.08,0 -1.92,-0.36 -2.53,-1.07c-0.61,-0.71 -0.93,-1.72 -0.94,-3.02V7.56c0,-1.39 0.28,-2.44 0.84,-3.13c0.56,-0.7 1.39,-1.04 2.51,-1.04c0.95,0 1.69,0.26 2.22,0.79c0.54,0.53 0.83,1.28 0.89,2.26h-1.25c-0.05,-0.62 -0.22,-1.1 -0.52,-1.45c-0.29,-0.35 -0.74,-0.52 -1.34,-0.52c-0.72,0 -1.24,0.23 -1.57,0.7C8.85,5.63 8.68,6.37 8.66,7.4v2.03c0,1 0.19,1.77 0.57,2.31c0.38,0.54 0.93,0.8 1.65,0.8c0.67,0 1.19,-0.16 1.54,-0.49l0.18,-0.17V9.59h-1.82V8.52h3.07V12.24z"/>
+ </group>
+</vector>
+
diff --git a/packages/SystemUI/res/layout/controls_management.xml b/packages/SystemUI/res/layout/controls_management.xml
index ae7f44d19430..b9e711e54b3b 100644
--- a/packages/SystemUI/res/layout/controls_management.xml
+++ b/packages/SystemUI/res/layout/controls_management.xml
@@ -50,7 +50,7 @@
<FrameLayout
android:layout_width="match_parent"
- android:layout_height="72dp">
+ android:layout_height="@dimen/controls_management_footer_height">
<View
android:layout_width="match_parent"
@@ -61,7 +61,8 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:padding="@dimen/controls_management_footer_side_margin">
+ android:paddingHorizontal="@dimen/controls_management_footer_side_margin"
+ android:paddingVertical="@dimen/controls_management_footer_top_margin" >
<Button
android:id="@+id/other_apps"
diff --git a/packages/SystemUI/res/layout/controls_management_favorites.xml b/packages/SystemUI/res/layout/controls_management_favorites.xml
index 4850e7534943..0ddd0e38acb9 100644
--- a/packages/SystemUI/res/layout/controls_management_favorites.xml
+++ b/packages/SystemUI/res/layout/controls_management_favorites.xml
@@ -36,7 +36,7 @@
android:layout_width="wrap_content"
android:layout_height="@dimen/controls_management_page_indicator_height"
android:layout_gravity="center"
- android:layout_marginTop="@dimen/controls_management_list_margin"
+ android:layout_marginTop="@dimen/controls_management_indicator_top_margin"
android:visibility="invisible" />
<androidx.viewpager2.widget.ViewPager2
diff --git a/packages/SystemUI/res/layout/controls_structure_page.xml b/packages/SystemUI/res/layout/controls_structure_page.xml
index f048d62d46d7..412ed566ff1b 100644
--- a/packages/SystemUI/res/layout/controls_structure_page.xml
+++ b/packages/SystemUI/res/layout/controls_structure_page.xml
@@ -21,4 +21,4 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
- android:layout_marginTop="@dimen/controls_management_zone_top_margin"/> \ No newline at end of file
+ android:layout_marginTop="@dimen/controls_management_favorites_top_margin"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 4fc65dcb4951..51397657f305 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Hervat"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Kanselleer"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Deel"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Vee uit"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Skermopname is gekanselleer"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Skermopname is gestoor, tik om te sien"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Skermopname is uitgevee"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Kon nie skermopname uitvee nie"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Kon nie toestemmings kry nie"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Kon nie skermopname begin nie"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 67d37739d43e..dad126cedee3 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ከቆመበት ቀጥል"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"ይቅር"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"አጋራ"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"ሰርዝ"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"የማያ ገጽ ቀረጻ ተሰርዟል"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"የማያ ገጽ ቀረጻ ተቀምጧል፣ ለመመልከት መታ ያድርጉ"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"የማያ ገጽ ቀረጻ ተሰርዟል"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"የማያ ገጽ ቀረጻን መሰረዝ ላይ ስህተት"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"ፈቃዶችን ማግኘት አልተቻለም"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"የማያ ገጽ ቀረጻን መጀመር ላይ ስህተት"</string>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index f4adeddafcec..18a1eba7a36b 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"استئناف"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"إلغاء"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"مشاركة"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"حذف"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"تمّ إلغاء تسجيل الشاشة."</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"تمّ حفظ تسجيل الشاشة، انقر لعرضه."</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"تمّ حذف تسجيل الشاشة."</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"حدث خطأ أثناء حذف تسجيل الشاشة."</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"تعذّر الحصول على أذونات."</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"حدث خطأ في بدء تسجيل الشاشة"</string>
@@ -234,7 +232,7 @@
<string name="not_default_data_content_description" msgid="6757881730711522517">"لم يتم الضبط على استخدام البيانات"</string>
<string name="cell_data_off" msgid="4886198950247099526">"غير مفعّلة"</string>
<string name="accessibility_bluetooth_tether" msgid="6327291292208790599">"التوصيل عبر البلوتوث"</string>
- <string name="accessibility_airplane_mode" msgid="1899529214045998505">"وضع الطائرة."</string>
+ <string name="accessibility_airplane_mode" msgid="1899529214045998505">"وضع الطيران."</string>
<string name="accessibility_vpn_on" msgid="8037549696057288731">"‏الشبكة الافتراضية الخاصة (VPN) قيد التفعيل."</string>
<string name="accessibility_no_sims" msgid="5711270400476534667">"‏ليس هناك شريحة SIM."</string>
<string name="carrier_network_change_mode" msgid="5174141476991149918">"جارٍ تغيير شبكة مشغِّل شبكة الجوّال."</string>
@@ -269,10 +267,10 @@
<string name="accessibility_quick_settings_wifi_changed_on" msgid="1490362586009027611">"‏تم تفعيل Wifi."</string>
<string name="accessibility_quick_settings_mobile" msgid="1817825313718492906">"الجوّال <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
<string name="accessibility_quick_settings_battery" msgid="533594896310663853">"البطارية <xliff:g id="STATE">%s</xliff:g>."</string>
- <string name="accessibility_quick_settings_airplane_off" msgid="1275658769368793228">"إيقاف وضع الطائرة."</string>
- <string name="accessibility_quick_settings_airplane_on" msgid="8106176561295294255">"تفعيل وضع الطائرة."</string>
- <string name="accessibility_quick_settings_airplane_changed_off" msgid="8880183481476943754">"تم إيقاف وضع الطائرة."</string>
- <string name="accessibility_quick_settings_airplane_changed_on" msgid="6327378061894076288">"تم تفعيل وضع الطائرة."</string>
+ <string name="accessibility_quick_settings_airplane_off" msgid="1275658769368793228">"إيقاف وضع الطيران."</string>
+ <string name="accessibility_quick_settings_airplane_on" msgid="8106176561295294255">"تفعيل وضع الطيران."</string>
+ <string name="accessibility_quick_settings_airplane_changed_off" msgid="8880183481476943754">"تم إيقاف وضع الطيران."</string>
+ <string name="accessibility_quick_settings_airplane_changed_on" msgid="6327378061894076288">"تم تفعيل وضع الطيران."</string>
<string name="accessibility_quick_settings_dnd_none_on" msgid="3235552940146035383">"كتم الصوت تمامًا"</string>
<string name="accessibility_quick_settings_dnd_alarms_on" msgid="3375848309132140014">"المنبِّهات فقط"</string>
<string name="accessibility_quick_settings_dnd" msgid="2415967452264206047">"عدم الإزعاج"</string>
@@ -320,7 +318,7 @@
<string name="data_usage_disabled_dialog" msgid="7933201635215099780">"تم الوصول إلى حد البيانات الذي عيَّنته. لم يُعد بإمكانك استخدام بيانات الجوال.\n\nفي حالة الاستئناف، قد يتم تطبيق الرسوم لاستخدام البيانات."</string>
<string name="data_usage_disabled_dialog_enable" msgid="2796648546086408937">"استئناف"</string>
<string name="gps_notification_searching_text" msgid="231304732649348313">"‏جارٍ البحث عن GPS"</string>
- <string name="gps_notification_found_text" msgid="3145873880174658526">"‏تم تعيين الموقع بواسطة GPS"</string>
+ <string name="gps_notification_found_text" msgid="3145873880174658526">"‏تم ضبط الموقع بواسطة GPS"</string>
<string name="accessibility_location_active" msgid="2845747916764660369">"طلبات الموقع نشطة"</string>
<string name="accessibility_sensors_off_active" msgid="2619725434618911551">"أجهزة الاستشعار غير مفعّلة"</string>
<string name="accessibility_clear_all" msgid="970525598287244592">"محو جميع الإشعارات."</string>
@@ -666,7 +664,7 @@
<string name="status_bar_ethernet" msgid="5690979758988647484">"إيثرنت"</string>
<string name="status_bar_alarm" msgid="87160847643623352">"المنبّه"</string>
<string name="status_bar_work" msgid="5238641949837091056">"الملف الشخصي للعمل"</string>
- <string name="status_bar_airplane" msgid="4848702508684541009">"وضع الطائرة"</string>
+ <string name="status_bar_airplane" msgid="4848702508684541009">"وضع الطيران"</string>
<string name="add_tile" msgid="6239678623873086686">"إضافة فئة"</string>
<string name="broadcast_tile" msgid="5224010633596487481">"إرسال فئة"</string>
<string name="zen_alarm_warning_indef" msgid="5252866591716504287">"لن تسمع المنبّه القادم في <xliff:g id="WHEN">%1$s</xliff:g> إلا إذا أوقفت هذا قبل الموعد"</string>
@@ -699,7 +697,7 @@
<string name="tuner_full_importance_settings" msgid="1388025816553459059">"عناصر التحكم في إشعارات التشغيل"</string>
<string name="tuner_full_importance_settings_on" msgid="917981436602311547">"تشغيل"</string>
<string name="tuner_full_importance_settings_off" msgid="5580102038749680829">"إيقاف"</string>
- <string name="power_notification_controls_description" msgid="1334963837572708952">"باستخدام عناصر التحكم في إشعار التشغيل، يمكنك تعيين مستوى الأهمية من 0 إلى 5 لإشعارات التطبيق. \n\n"<b>"المستوى 5"</b>" \n- العرض أعلى قائمة الإشعارات \n- يسمح بمقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 4"</b>" \n- منع مقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 3"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n\n"<b>"المستوى 2"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات واهتزاز \n\n"<b>"المستوى 1"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات أو اهتزاز أبدًا \n- الإخفاء من شاشة القفل وشريط الحالة \n- العرض أسفل قائمة الإشعارات \n\n"<b>"المستوى 0"</b>" \n- حظر جميع الإشعارات من التطبيق"</string>
+ <string name="power_notification_controls_description" msgid="1334963837572708952">"باستخدام عناصر التحكم في إشعار التشغيل، يمكنك ضبط مستوى الأهمية من 0 إلى 5 لإشعارات التطبيق. \n\n"<b>"المستوى 5"</b>" \n- العرض أعلى قائمة الإشعارات \n- يسمح بمقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 4"</b>" \n- منع مقاطعة ملء الشاشة \n- الظهور الخاطف دائمًا \n\n"<b>"المستوى 3"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n\n"<b>"المستوى 2"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات واهتزاز \n\n"<b>"المستوى 1"</b>" \n- منع مقاطعة ملء الشاشة \n- عدم الظهور الخاطف أبدًا \n- عدم إصدار أصوات أو اهتزاز أبدًا \n- الإخفاء من شاشة القفل وشريط الحالة \n- العرض أسفل قائمة الإشعارات \n\n"<b>"المستوى 0"</b>" \n- حظر جميع الإشعارات من التطبيق"</string>
<string name="notification_header_default_channel" msgid="225454696914642444">"الإشعارات"</string>
<string name="notification_channel_disabled" msgid="928065923928416337">"لن تتلقى هذه الإشعارات بعد الآن."</string>
<string name="notification_channel_minimized" msgid="6892672757877552959">"سيتم تصغير هذه الإشعارات."</string>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 8fd20dfc4a8d..9185d95bf9dd 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ৰখোৱাৰ পৰা পুনৰ আৰম্ভ কৰক"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"বাতিল কৰক"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"শ্বেয়াৰ কৰক"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"মচক"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"স্ক্রীণ ৰেকৰ্ড কৰাটো বাতিল কৰা হ’ল"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"স্ক্রীণ ৰেকৰ্ডিং ছেভ কৰা হ’ল, চাবলৈ টিপক"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"স্ক্রীণ ৰেকৰ্ডিং মচা হ’ল"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"স্ক্রীণ ৰেকৰ্ডিং মচি থাকোঁতে কিবা আসোঁৱাহ হ’ল"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"অনুমতি পাব পৰা নগ\'ল"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"স্ক্রীন ৰেকৰ্ড কৰা আৰম্ভ কৰোঁতে আসোঁৱাহ হৈছে"</string>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index f45fe634b5a9..933bb044b5dc 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Davam edin"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Ləğv edin"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Paylaşın"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Silin"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Ekranın video çəkimi ləğv edildi"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Ekranın video çəkimi yadda saxlanıldı. Baxmaq üçün klikləyin"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Ekranın video çəkimi silindi"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Ekranın video çəkiminin silinməsi zamanı xəta baş verdi"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"İcazələr əldə edilmədi"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Ekranın yazılması ilə bağlı xəta"</string>
@@ -405,7 +403,7 @@
<item quantity="one">%d cihaz</item>
</plurals>
<string name="quick_settings_notifications_label" msgid="3379631363952582758">"Bildirişlər"</string>
- <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"İşartı"</string>
+ <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Fənər"</string>
<string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Kamera istifadə olunur"</string>
<string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Mobil data"</string>
<string name="quick_settings_cellular_detail_data_usage" msgid="6105969068871138427">"Data istifadəsi"</string>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index daac5028f4ca..abb8a3a9122d 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Nastavi"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Otkaži"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Deli"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Izbriši"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Snimanje ekrana je otkazano"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Snimak ekrana je sačuvan, dodirnite da biste pregledali"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Snimak ekrana je izbrisan"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Došlo je do problema pri brisanju snimka ekrana"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Preuzimanje dozvola nije uspelo"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Greška pri pokretanju snimanja ekrana"</string>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 50227525fa07..6fcc5cff69ef 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Узнавіць"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Скасаваць"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Абагуліць"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Выдаліць"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Запіс экрана скасаваны"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Запіс экрана захаваны. Націсніце, каб прагледзець"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Запіс экрана выдалены"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Памылка выдалення запісу экрана"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Не ўдалося атрымаць дазволы"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Памылка пачатку запісу экрана"</string>
@@ -722,7 +720,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"У залежнасці ад налад тэлефона магчымы званок або вібрацыя"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"У залежнасці ад налад тэлефона магчымы званок або вібрацыя. Размовы ў праграме \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" стандартна паяўляюцца ў выглядзе ўсплывальных апавяшчэнняў."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Прыцягвае ўвагу да гэтага змесціва ўсплывальнай кнопкай."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Паказваецца ўверсе раздзела размоў у выглядзе ўсплывальнага апавяшчэння, а на экране блакіроўкі – у выглядзе відарыса профілю"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Паказваецца ўверсе раздзела размоў, як усплывальнае апавяшчэнне, паказвае фота профілю на экране блакіроўкі"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Налады"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Прыярытэт"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не падтрымлівае функцыі размовы"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 599cd6007b16..e24ece4b296a 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Възобновяване"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Отказ"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Споделяне"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Изтриване"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Записването на екрана е анулирано"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Записът на екрана е запазен. Докоснете, за да го видите"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Записът на екрана е изтрит"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"При изтриването на записа на екрана възникна грешка"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Извличането на разрешенията не бе успешно."</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"При стартирането на записа на екрана възникна грешка"</string>
@@ -716,7 +714,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Може да звъни или да вибрира въз основа на настройките за телефона"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може да звъни или да вибрира въз основа на настройките за телефона. Разговорите от <xliff:g id="APP_NAME">%1$s</xliff:g> се показват като балончета по подразбиране."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Задържа вниманието ви посредством плаващ пряк път към това съдържание."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Показва се като плаващо балонче в горната част на секцията с разговори и показва снимката на потребителския профил на заключения екран"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Показва се като плаващо балонче в горната част на секцията с разговори, показва снимката на потр. профил на заключения екран"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Настройки"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не поддържа функциите за разговор"</string>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 657022b6a4ae..24805e067d12 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"আবার চালু করুন"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"বাতিল করুন"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"শেয়ার করুন"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"মুছুন"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"স্ক্রিন রেকর্ডিং বাতিল করা হয়েছে"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"স্ক্রিন রেকর্ডিং সেভ করা হয়েছে, দেখতে ট্যাপ করুন"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"স্ক্রিন রেকর্ডিং মুছে ফেলা হয়েছে"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"স্ক্রিন রেকডিং মুছে ফেলার সময় সমস্যা হয়েছে"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"অনুমতি পাওয়া যায়নি"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"স্ক্রিন রেকর্ডিং শুরু করার সময় সমস্যা হয়েছে"</string>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index a51e79a42da7..830929cf2d00 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Nastavi"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Otkaži"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Dijeli"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Izbriši"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Snimanje ekrana je otkazano"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Snimak ekrana je sačuvan. Dodirnite za prikaz."</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Snimak ekrana je izbrisan"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Greška prilikom brisanja snimka ekrana"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Dobijanje odobrenja nije uspjelo"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Greška pri pokretanju snimanja ekrana"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 5a70913c4fe3..529e37a59e07 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Reprèn"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancel·la"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Comparteix"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Suprimeix"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"S\'ha cancel·lat la gravació de la pantalla"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"S\'ha desat la gravació de la pantalla; toca per mostrar"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"S\'ha suprimit la gravació de la pantalla"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"S\'ha produït un error en suprimir la gravació de la pantalla"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"No s\'han pogut obtenir els permisos"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"S\'ha produït un error en iniciar la gravació de pantalla"</string>
@@ -709,7 +707,7 @@
<string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desactiva les notificacions"</string>
<string name="inline_keep_showing_app" msgid="4393429060390649757">"Vols continuar rebent notificacions d\'aquesta aplicació?"</string>
<string name="notification_silence_title" msgid="8608090968400832335">"Silenci"</string>
- <string name="notification_alert_title" msgid="3656229781017543655">"Predeterminada"</string>
+ <string name="notification_alert_title" msgid="3656229781017543655">"Predeterminat"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"Bombolla"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Sense so ni vibració"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sense so ni vibració i es mostra més avall a la secció de converses"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index a4e831a256c3..0851910e7ea1 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -95,7 +95,7 @@
<string name="screenrecord_description" msgid="1123231719680353736">"Při nahrávání může systém Android zaznamenávat citlivé údaje, které jsou viditelné na obrazovce nebo které jsou přehrávány na zařízení. Týká se to hesel, údajů o platbě, fotek, zpráv a zvuků."</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Nahrát zvuk"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvuk zařízení"</string>
- <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk ze zařízení, například hudba, hovory a vyzváněcí tóny"</string>
+ <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvuk ze zařízení, například hudba, hovory a vyzvánění"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Mikrofon"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Zvuk a mikrofon zařízení"</string>
<string name="screenrecord_start" msgid="330991441575775004">"Spustit"</string>
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Obnovit"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Zrušit"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Sdílet"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Smazat"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Nahrávání obrazovky bylo zrušeno"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Záznam obrazovky byl uložen, zobrazíte jej klepnutím"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Záznam obrazovky byl smazán"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Při mazání záznamu obrazovky došlo k chybě"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Nepodařilo se načíst oprávnění"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Při spouštění nahrávání obrazovky došlo k chybě"</string>
@@ -722,7 +720,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Může vyzvánět nebo vibrovat v závislosti na nastavení telefonu"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Může vyzvánět nebo vibrovat v závislosti na nastavení telefonu. Konverzace z aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> ve výchozím nastavení bublají."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Přitahuje pozornost pomocí plovoucí zkratky k tomuto obsahu."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Zobrazuje se v horní části sekce konverzace a má podobu plovoucí bubliny, zobrazuje profilovou fotku na obrazovce uzamčení"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Zobrazuje se v horní části sekce konverzací a má podobu plovoucí bubliny, zobrazuje profilovou fotku na obrazovce uzamčení"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Nastavení"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priorita"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Aplikace <xliff:g id="APP_NAME">%1$s</xliff:g> funkce konverzace nepodporuje"</string>
@@ -1035,7 +1033,7 @@
<string name="inattentive_sleep_warning_title" msgid="3891371591713990373">"Pohotovostní režim"</string>
<string name="priority_onboarding_title" msgid="2893070698479227616">"Konverzace byla nastavena jako prioritní"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"Chování prioritních konverzací:"</string>
- <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Zobrazovat v horní části sekce konverzace"</string>
+ <string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"Zobrazovat v horní části sekce konverzací"</string>
<string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"Zobrazovat profilovou fotku na zámku obrazovky"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"Zobrazuje se jako plovoucí bublina nad aplikacemi"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"Přerušit režim Nerušit"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index c8a61a7051c8..9bd741517bcd 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Genoptag"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Annuller"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Del"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Slet"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Skærmoptagelsen er annulleret"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Skærmoptagelsen er gemt. Tryk for at se den."</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Skærmoptagelsen er slettet"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Der opstod en fejl ved sletning af skærmoptagelsen"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Det lykkedes ikke et hente tilladelserne"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Skærmoptagelsen kunne ikke startes"</string>
@@ -716,7 +714,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Kan ringe eller vibrere baseret på telefonens indstillinger"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan ringe eller vibrere baseret på telefonens indstillinger. Samtaler fra <xliff:g id="APP_NAME">%1$s</xliff:g> vises som standard i bobler."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Fastholder din opmærksomhed med en svævende genvej til indholdet."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Vises øverst i samtalesektionen, som en svævende boble og med profilbillede på låseskærmen"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Vises øverst i samtalesektionen som en svævende boble og med profilbillede på låseskærmen"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Indstillinger"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioritet"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> understøtter ikke samtalefunktioner"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 787f927d85f0..e4f5ac2f0e25 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Fortsetzen"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Abbrechen"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Teilen"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Löschen"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Bildschirmaufzeichnung abgebrochen"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Bildschirmaufzeichnung gespeichert, zum Ansehen tippen"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Bildschirmaufzeichnung gelöscht"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Fehler beim Löschen der Bildschirmaufzeichnung"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Berechtigungen nicht erhalten"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Fehler beim Start der Bildschirmaufzeichnung"</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index a2865b182c31..76bd133853f0 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Συνέχιση"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Ακύρωση"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Κοινοποίηση"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Διαγραφή"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Η εγγραφή οθόνης ακυρώθηκε"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Η εγγραφή οθόνης αποθηκεύτηκε. Πατήστε για προβολή."</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Η εγγραφή οθόνης διαγράφηκε"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Παρουσιάστηκε σφάλμα κατά τη διαγραφή της εγγραφής οθόνης"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Η λήψη αδειών απέτυχε"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Σφάλμα κατά την έναρξη της εγγραφής οθόνης"</string>
@@ -693,7 +691,7 @@
<string name="notification_channel_minimized" msgid="6892672757877552959">"Αυτές οι ειδοποιήσεις θα ελαχιστοποιηθούν"</string>
<string name="notification_channel_silenced" msgid="1995937493874511359">"Αυτές οι ειδοποιήσεις θα εμφανίζονται σιωπηλά"</string>
<string name="notification_channel_unsilenced" msgid="94878840742161152">"Αυτές οι ειδοποιήσεις θα σας ενημερώνουν"</string>
- <string name="inline_blocking_helper" msgid="2891486013649543452">"Συνήθως απορρίπτετε αυτές τις ειδοποιήσεις. \nΝα εξακολουθήσουν να εμφανίζονται;"</string>
+ <string name="inline_blocking_helper" msgid="2891486013649543452">"Συνήθως παραβλέπετε αυτές τις ειδοποιήσεις. \nΝα εξακολουθήσουν να εμφανίζονται;"</string>
<string name="inline_done_button" msgid="6043094985588909584">"Τέλος"</string>
<string name="inline_ok_button" msgid="603075490581280343">"Εφαρμογή"</string>
<string name="inline_keep_showing" msgid="8736001253507073497">"Να συνεχίσουν να εμφανίζονται αυτές οι ειδοποιήσεις;"</string>
@@ -716,7 +714,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Ενδέχεται να κουδουνίζει ή να δονείται βάσει των ρυθμίσεων του τηλεφώνου"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Ενδέχεται να κουδουνίζει ή να δονείται βάσει των ρυθμίσεων του τηλεφώνου. Οι συζητήσεις από την εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> εμφανίζονται σε συννεφάκι από προεπιλογή."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Κρατάει την προσοχή σας με μια κινούμενη συντόμευση προς αυτό το περιεχόμενο."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Εμφανίζεται στο επάνω μέρος της ενότητας συζητήσεων, προβάλλεται ως κινούμενο συννεφάκι, εμφανίζει τη φωτογραφία προφίλ στην οθόνη κλειδώματος"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Εμφανίζεται επάνω στις συζητήσεις, προβάλλεται ως κιν. συννεφάκι, εμφανίζει τη φωτ. προφίλ στην οθ. κλειδ."</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ρυθμίσεις"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Προτεραιότητα"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Η εφαρμογή <xliff:g id="APP_NAME">%1$s</xliff:g> δεν υποστηρίζει τις λειτουργίες συζήτησης"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index a96f3ef83a32..3a52a7269186 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancel"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Share"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Delete"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Screen recording cancelled"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Screen recording saved, tap to view"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Screen recording deleted"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Error deleting screen recording"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Failed to get permissions"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Error starting screen recording"</string>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index 931df88f4cd2..11e0fb9a1852 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancel"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Share"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Delete"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Screen recording cancelled"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Screen recording saved, tap to view"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Screen recording deleted"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Error deleting screen recording"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Failed to get permissions"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Error starting screen recording"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index a96f3ef83a32..3a52a7269186 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancel"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Share"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Delete"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Screen recording cancelled"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Screen recording saved, tap to view"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Screen recording deleted"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Error deleting screen recording"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Failed to get permissions"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Error starting screen recording"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index a96f3ef83a32..3a52a7269186 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Resume"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancel"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Share"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Delete"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Screen recording cancelled"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Screen recording saved, tap to view"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Screen recording deleted"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Error deleting screen recording"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Failed to get permissions"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Error starting screen recording"</string>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index dbb6eb7ef76b..1a02d596ca14 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‎‎‎‎‎‏‏‏‎‎‎‏‎‏‎‎‎‎‎‏‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‏‏‏‎‏‏‏‎Resume‎‏‎‎‏‎"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‏‏‏‎‎Cancel‎‏‎‎‏‎"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‏‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‏‏‏‏‏‎‎‎‏‎‎‏‎‎Share‎‏‎‎‏‎"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‏‎‎‏‏‏‎‎‎‏‎‎‎‏‎‏‎‎‎‎‎‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‎‎Delete‎‏‎‎‏‎"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎‏‏‏‎‎‏‏‎‏‎‏‏‎‏‏‏‎‏‏‎‏‎Screen recording canceled‎‏‎‎‏‎"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‎‏‎‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‎‎‏‎‎‎‏‎‎‏‏‎‎‎‏‎‏‎‎‏‎‎Screen recording saved, tap to view‎‏‎‎‏‎"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‏‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‎‏‏‏‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎Screen recording deleted‎‏‎‎‏‎"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‎‎‎‏‏‎‏‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‎‎‎‎‎‎‏‎‏‏‎‏‎‏‎‎‎Error deleting screen recording‎‏‎‎‏‎"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‏‎‎‎‏‏‎‏‏‎‏‏‏‏‎‏‎‎‏‎‎‏‏‎‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‏‎‎‏‎‏‏‎‎Failed to get permissions‎‏‎‎‏‎"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‏‎‏‎‎‎‏‎‎‏‏‏‏‎‏‎‏‏‏‏‏‏‎‎‏‏‎‏‎‏‎‏‎‏‎‎‏‏‏‎‏‎‎‎‎‎‎‎Error starting screen recording‎‏‎‎‏‎"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index de86271dca0e..87a7f8fe59a6 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Reanudar"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancelar"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Compartir"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Borrar"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Se canceló la grabación de pantalla"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Se guardó la grabación de pantalla; presiona para verla"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Se borró la grabación de pantalla"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Error al borrar la grabación de pantalla"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Error al obtener permisos"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Error al iniciar la grabación de pantalla"</string>
@@ -708,17 +706,17 @@
<string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"Seguir recibiendo alertas"</string>
<string name="inline_turn_off_notifications" msgid="8543989584403106071">"Desactivar notificaciones"</string>
<string name="inline_keep_showing_app" msgid="4393429060390649757">"¿Quieres seguir viendo las notificaciones de esta app?"</string>
- <string name="notification_silence_title" msgid="8608090968400832335">"Silencio"</string>
+ <string name="notification_silence_title" msgid="8608090968400832335">"Silenciada"</string>
<string name="notification_alert_title" msgid="3656229781017543655">"Predeterminada"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"Cuadro"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Sin sonido ni vibración"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"No suena ni vibra, y aparece en una parte inferior de la sección de conversaciones"</string>
- <string name="notification_channel_summary_default" msgid="3282930979307248890">"Puede sonar o vibrar en función de la configuración del teléfono"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"No suena ni vibra, y aparece en la parte inferior de la sección de conversaciones."</string>
+ <string name="notification_channel_summary_default" msgid="3282930979307248890">"Puede sonar o vibrar en función de la configuración del teléfono."</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Puede sonar o vibrar en función de la configuración del teléfono. Conversaciones de la burbuja de <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Retiene tu atención con un acceso directo flotante a este contenido."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece en la parte superior de la sección de conversaciones, en forma de burbuja flotante, y muestra la foto de perfil en la pantalla de bloqueo"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece en la parte superior de la sección de conversaciones, en forma de burbuja flotante, y muestra la foto de perfil en la pantalla de bloqueo."</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuración"</string>
- <string name="notification_priority_title" msgid="2079708866333537093">"Prioridad"</string>
+ <string name="notification_priority_title" msgid="2079708866333537093">"Prioritaria"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> no admite funciones de conversación"</string>
<string name="bubble_overflow_empty_title" msgid="3120029421991510842">"No hay burbujas recientes"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Las burbujas recientes y las que se descartaron aparecerán aquí"</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index ef4e7522002d..ec6e79f9d02b 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -98,7 +98,7 @@
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Sonido de tu dispositivo, como música, llamadas y tonos de llamada"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Micrófono"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Audio y micrófono del dispositivo"</string>
- <string name="screenrecord_start" msgid="330991441575775004">"Empezar"</string>
+ <string name="screenrecord_start" msgid="330991441575775004">"Iniciar"</string>
<string name="screenrecord_ongoing_screen_only" msgid="4459670242451527727">"Grabando pantalla"</string>
<string name="screenrecord_ongoing_screen_and_audio" msgid="5351133763125180920">"Grabando pantalla y audio"</string>
<string name="screenrecord_taps_label" msgid="1595690528298857649">"Mostrar toques en la pantalla"</string>
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Seguir"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancelar"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Compartir"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Eliminar"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Se ha cancelado la grabación de la pantalla"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Se ha guardado la grabación de la pantalla; toca para verla"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Se ha eliminado la grabación de la pantalla"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"No se ha podido eliminar la grabación de la pantalla"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"No se han podido obtener los permisos"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"No se ha podido empezar a grabar la pantalla"</string>
@@ -397,7 +395,7 @@
<string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"Conectado (<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> de batería)"</string>
<string name="quick_settings_connecting" msgid="2381969772953268809">"Conectando..."</string>
<string name="quick_settings_tethering_label" msgid="5257299852322475780">"Compartir conexión"</string>
- <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Zona Wi-Fi"</string>
+ <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Punto de acceso"</string>
<string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Activando…"</string>
<string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Ahorro de datos activado"</string>
<plurals name="quick_settings_hotspot_secondary_label_num_devices" formatted="false" msgid="3142308865165871976">
@@ -662,7 +660,7 @@
<string name="alarm_template" msgid="2234991538018805736">"a las <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="alarm_template_far" msgid="3561752195856839456">"el <xliff:g id="WHEN">%1$s</xliff:g>"</string>
<string name="accessibility_quick_settings_detail" msgid="544463655956179791">"Ajustes rápidos, <xliff:g id="TITLE">%s</xliff:g>."</string>
- <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"Zona Wi-Fi"</string>
+ <string name="accessibility_status_bar_hotspot" msgid="2888479317489131669">"Punto de acceso"</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>
@@ -712,11 +710,11 @@
<string name="notification_alert_title" msgid="3656229781017543655">"Predeterminado"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"Burbuja"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Sin sonido ni vibración"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sin sonido ni vibración y se muestra más abajo en la sección de conversaciones"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sin sonido ni vibración, y se muestra más abajo en la sección de conversaciones"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Es posible que suene o vibre según los ajustes del teléfono"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Es posible que suene o vibre según los ajustes del teléfono. Las conversaciones de <xliff:g id="APP_NAME">%1$s</xliff:g> aparecen como burbujas de forma predeterminada."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Llama tu atención con un acceso directo flotante a este contenido."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Se muestra arriba en la sección de conversaciones en forma de burbuja flotante, y la imagen de perfil aparece en la pantalla de bloqueo"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Se muestra arriba en la sección de conversaciones, como burbuja flotante, y la imagen de perfil aparece en la pantalla de bloqueo"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Ajustes"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioridad"</string>
<string name="no_shortcut" msgid="8257177117568230126">"No se pueden usar funciones de conversación con <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index 9a12f54608b1..ec91fcddf1da 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Jätka"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Tühista"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Jaga"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Kustuta"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Ekraanikuva salvestamine on tühistatud"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Ekraanikuva salvestis on salvestatud, puudutage vaatamiseks"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Ekraanikuva salvestis on kustutatud"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Viga ekraanikuva salvestise kustutamisel"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Lubade hankimine ebaõnnestus"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Viga ekraanikuva salvestamise alustamisel"</string>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index d0bf329fa46e..9598ddddb8f7 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Berrekin"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Utzi"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Partekatu"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Ezabatu"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Utzi zaio pantaila grabatzeari"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Gorde da pantailaren grabaketa; sakatu ikusteko"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Ezabatu da pantailaren grabaketa"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Errore bat gertatu da pantailaren grabaketa ezabatzean"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Ezin izan dira lortu baimenak"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Errore bat gertatu da pantaila grabatzen hastean"</string>
@@ -554,7 +552,7 @@
<string name="monitoring_description_named_vpn" msgid="5749932930634037027">"<xliff:g id="VPN_APP">%1$s</xliff:g> aplikaziora konektatuta zaude eta hark sareko jarduerak gainbegira ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
<string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> eta <xliff:g id="VPN_APP_1">%2$s</xliff:g> aplikazioetara konektatuta zaude, eta haiek sareko jarduerak gainbegira ditzakete, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
<string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"<xliff:g id="VPN_APP">%1$s</xliff:g> aplikaziora dago konektatuta laneko profila, eta aplikazio horrek sareko jarduerak gainbegira ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
- <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"<xliff:g id="VPN_APP">%1$s</xliff:g> aplikaziora konektatuta duzu profil pertsonala, eta aplikazio horrek sareko jarduerak gainbegira ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
+ <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"<xliff:g id="VPN_APP">%1$s</xliff:g> aplikaziora konektatuta daukazu profil pertsonala, eta aplikazio horrek sareko jarduerak gainbegira ditzake, mezu elektronikoak, aplikazioak eta webguneak barne."</string>
<string name="monitoring_description_do_header_generic" msgid="6130190408164834986">"<xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> aplikazioak kudeatzen du gailu hau."</string>
<string name="monitoring_description_do_header_with_name" msgid="2696255132542779511">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> erakundeak <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> erabiltzen du gailua kudeatzeko."</string>
<string name="monitoring_description_do_body" msgid="7700878065625769970">"Gailuko ezarpenak, enpresa-sarbidea, aplikazioak eta datuak gainbegira eta kudea ditzake administratzaileak, baita gailuaren kokapen-informazioa ere."</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 52ba23e17a32..410edfb74eb7 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ازسرگیری"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"لغو"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"هم‌رسانی"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"حذف"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"ضبط صفحه‌نمایش لغو شد"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"ضبط صفحه‌نمایش ذخیره شد، برای مشاهده ضربه بزنید"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"فایل ضبط صفحه‌نمایش حذف شد"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"خطا در حذف فایل ضبط صفحه‌نمایش"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"مجوزها دریافت نشدند"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"خطا هنگام شروع ضبط صفحه‌نمایش"</string>
@@ -802,7 +800,7 @@
<string name="keyboard_shortcut_group_system_back" msgid="1055709713218453863">"برگشت"</string>
<string name="keyboard_shortcut_group_system_notifications" msgid="3615971650562485878">"اعلان‌ها"</string>
<string name="keyboard_shortcut_group_system_shortcuts_helper" msgid="4856808328618265589">"میان‌برهای صفحه‌کلید"</string>
- <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تغییر طرح‌بندی صفحه‌کلید"</string>
+ <string name="keyboard_shortcut_group_system_switch_input" msgid="952555530383268166">"تغییر جانمایی صفحه‌کلید"</string>
<string name="keyboard_shortcut_group_applications" msgid="7386239431100651266">"برنامه‌ها"</string>
<string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"دستیار"</string>
<string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"مرورگر"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 332c512b1772..72e16203b4c7 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Jatka"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Peruuta"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Jaa"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Poista"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Näytön tallennus peruutettu"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Näyttötallenne tallennettu, katso napauttamalla"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Näyttötallenne poistettu"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Virhe poistettaessa näyttötallennetta"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Käyttöoikeuksien hakeminen epäonnistui."</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Virhe näytön tallennuksen aloituksessa"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index e1942a4ed98b..91bb30f8dc3d 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Reprendre"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Annuler"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Partager"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Supprimer"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"L\'enregistrement d\'écran a été annulé"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"L\'enregistrement d\'écran est terminé. Touchez ici pour l\'afficher."</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"L\'enregistrement d\'écran a été supprimé"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Une erreur s\'est produite lors de la suppression de l\'enregistrement d\'écran"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Impossible d\'obtenir les autorisations"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Une erreur s\'est produite lors du démarrage de l\'enregistrement d\'écran"</string>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 7fb9e968ec33..59b9cfc8a949 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Reprendre"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Annuler"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Partager"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Supprimer"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Enregistrement de l\'écran annulé"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Enregistrement de l\'écran enregistré. Appuyez pour afficher"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Enregistrement de l\'écran supprimé"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Erreur lors de la suppression de l\'enregistrement de l\'écran"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Échec d\'obtention des autorisations"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Erreur lors du démarrage de l\'enregistrement de l\'écran"</string>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 29be995a6cca..d22bd33f3f45 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancelar"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Compartir"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Eliminar"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Cancelouse a gravación de pantalla"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Gardouse a gravación de pantalla; toca esta notificación para visualizala"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Eliminouse a gravación de pantalla"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Produciuse un erro ao eliminar a gravación de pantalla"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Produciuse un erro ao obter os permisos"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Produciuse un erro ao iniciar a gravación da pantalla"</string>
@@ -712,11 +710,11 @@
<string name="notification_alert_title" msgid="3656229781017543655">"Configuración predeterminada"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"Burbulla"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Sen son nin vibración"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Non soa nin vibra, e aparece máis abaixo na sección de conversas"</string>
- <string name="notification_channel_summary_default" msgid="3282930979307248890">"Podería soar ou vibrar en función da configuración do teléfono"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Sen son nin vibración, e aparecen máis abaixo na sección de conversas"</string>
+ <string name="notification_channel_summary_default" msgid="3282930979307248890">"Poderían soar ou vibrar en función da configuración do teléfono"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Podería soar ou vibrar en función da configuración do teléfono. Conversas desde a burbulla da aplicación <xliff:g id="APP_NAME">%1$s</xliff:g> de forma predeterminada."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantén a túa atención cun atallo flotante a este contido."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Móstrase na parte superior da sección de conversas en forma de burbulla flotante e aparece a imaxe do perfil na pantalla de bloqueo"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Móstranse na parte superior da sección de conversas en forma de burbulla flotante e aparece a imaxe do perfil na pantalla de bloqueo"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configuración"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> non admite funcións de conversa"</string>
@@ -786,7 +784,7 @@
<string name="keyboard_key_media_stop" msgid="1509943745250377699">"Deter"</string>
<string name="keyboard_key_media_next" msgid="8502476691227914952">"Seguinte"</string>
<string name="keyboard_key_media_previous" msgid="5637875709190955351">"Anterior"</string>
- <string name="keyboard_key_media_rewind" msgid="3450387734224327577">"Rebobinar"</string>
+ <string name="keyboard_key_media_rewind" msgid="3450387734224327577">"Retroceder"</string>
<string name="keyboard_key_media_fast_forward" msgid="3572444327046911822">"Avance rápido"</string>
<string name="keyboard_key_page_up" msgid="173914303254199845">"Re Páx"</string>
<string name="keyboard_key_page_down" msgid="9035902490071829731">"Av Páx"</string>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index bafa026ce4ce..a5d806b27793 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ફરી શરૂ કરો"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"રદ કરો"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"શેર કરો"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"ડિલીટ કરો"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"સ્ક્રીન રેકોર્ડિંગ રદ કર્યું"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"સ્ક્રીન રેકોર્ડિંગ સાચવ્યું, જોવા માટે ટૅપ કરો"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"સ્ક્રીન રેકોર્ડિંગ ડિલીટ કર્યું"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"સ્ક્રીન રેકોર્ડિંગ ડિલીટ કરવામાં ભૂલ આવી"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"પરવાનગીઓ મેળવવામાં નિષ્ફળ રહ્યાં"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"સ્ક્રીનને રેકૉર્ડ કરવાનું શરૂ કરવામાં ભૂલ"</string>
@@ -859,7 +857,7 @@
<string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"ટાઇલને ફરીથી ગોઠવવા માટે આંગળી દબાવીને ખેંચો"</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"દૂર કરવા માટે અહીં ખેંચો"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"તમને ઓછામાં ઓછી <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> ટાઇલની જરૂર છે"</string>
- <string name="qs_edit" msgid="5583565172803472437">"સંપાદિત કરો"</string>
+ <string name="qs_edit" msgid="5583565172803472437">"ફેરફાર કરો"</string>
<string name="tuner_time" msgid="2450785840990529997">"સમય"</string>
<string-array name="clock_options">
<item msgid="3986445361435142273">"કલાક, મિનિટ અને સેકન્ડ બતાવો"</item>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index be2cd0bd2218..ae51e2e176b8 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"फिर से शुरू करें"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"रद्द करें"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"शेयर करें"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"मिटाएं"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"स्क्रीन रिकॉर्डिंग रद्द कर दी गई"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"स्क्रीन रिकॉर्डिंग सेव की गई, देखने के लिए टैप करें"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"स्क्रीन रिकॉर्डिंग मिटा दी गई"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"स्क्रीन रिकॉर्डिंग मिटाने में गड़बड़ी हुई"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"मंज़ूरी नहीं मिल सकी"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"स्क्रीन को रिकॉर्ड करने में गड़बड़ी आ रही है"</string>
@@ -514,7 +512,7 @@
<string name="manage_notifications_history_text" msgid="57055985396576230">"इतिहास"</string>
<string name="notification_section_header_incoming" msgid="850925217908095197">"नई सूचनाएं"</string>
<string name="notification_section_header_gentle" msgid="6804099527336337197">"बिना आवाज़ किए मिलने वाली सूचनाएं"</string>
- <string name="notification_section_header_alerting" msgid="5581175033680477651">"वाइब्रेशन या आवाज़ के साथ मिलने वाली सूचनाएं"</string>
+ <string name="notification_section_header_alerting" msgid="5581175033680477651">"सूचनाएं"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"बातचीत"</string>
<string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"बिना आवाज़ की सभी सूचनाएं हटाएं"</string>
<string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"\'परेशान न करें\' सुविधा के ज़रिए कुछ समय के लिए सूचनाएं दिखाना रोक दिया गया है"</string>
@@ -714,11 +712,11 @@
<string name="notification_alert_title" msgid="3656229781017543655">"डिफ़ॉल्ट"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"बबल"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"किसी तरह की आवाज़ या वाइब्रेशन न हो"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"इससे किसी तरह की आवाज़ या वाइब्रेशन नहीं होता और \'बातचीत\', सेक्शन में सबसे नीचे दिखती है"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"इससे किसी तरह की आवाज़ या वाइब्रेशन नहीं होता और बातचीत, सेक्शन में सबसे नीचे दिखती है"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"फ़ोन की सेटिंग के आधार पर, सूचना आने पर घंटी बज सकती है या वाइब्रेशन हो सकता है"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फ़ोन की सेटिंग के आधार पर, सूचना आने पर घंटी बज सकती है या वाइब्रेशन हो सकता है. <xliff:g id="APP_NAME">%1$s</xliff:g> में होने वाली बातचीत, डिफ़ॉल्ट रूप से बबल के तौर पर दिखती है."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"फ़्लोट करने वाले शॉर्टकट की मदद से इस सामग्री पर आपका ध्यान बना रहता है."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"इससे बातचीत की सुविधा, सेक्शन में सबसे ऊपर और फ़्लोटिंग बबल के तौर पर दिखती है. साथ ही, लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो दिखती है"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"इससे बातचीत, सेक्शन में सबसे ऊपर और फ़्लोटिंग बबल के तौर पर दिखती है. साथ ही, लॉक स्क्रीन पर प्रोफ़ाइल फ़ोटो दिखती है"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"सेटिंग"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> पर बातचीत की सुविधाएं काम नहीं करतीं"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 96880773f19e..3ebaef95112d 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Nastavi"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Odustani"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Dijeli"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Izbriši"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Snimanje zaslona otkazano"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Snimanje zaslona spremljeno je, dodirnite da biste ga pregledali"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Snimanje zaslona izbrisano"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Pogreška prilikom brisanja snimanja zaslona"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Dohvaćanje dopuštenja nije uspjelo"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Pogreška prilikom pokretanja snimanja zaslona"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 607c05a13468..05cf98431759 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Folytatás"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Mégse"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Megosztás"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Törlés"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"A képernyő rögzítése megszakítva"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Képernyőfelvétel mentve, koppintson a megtekintéshez"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"A képernyőről készült felvétel törölve"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Hiba történt a képernyőről készült felvétel törlésekor"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Nincs engedély"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Hiba a képernyőrögzítés indításakor"</string>
@@ -430,7 +428,7 @@
<string name="quick_settings_nfc_off" msgid="3465000058515424663">"Az NFC ki van kapcsolva"</string>
<string name="quick_settings_nfc_on" msgid="1004976611203202230">"Az NFC be van kapcsolva"</string>
<string name="quick_settings_screen_record_label" msgid="1594046461509776676">"Képernyő rögzítése"</string>
- <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Kezdés"</string>
+ <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"Indítás"</string>
<string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"Leállítás"</string>
<string name="media_seamless_remote_device" msgid="177033467332920464">"Eszköz"</string>
<string name="recents_swipe_up_onboarding" msgid="2820265886420993995">"Váltás az alkalmazások között felfelé csúsztatással"</string>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 56b8d32a1324..6c557443fb3b 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Վերսկսել"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Չեղարկել"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Կիսվել"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Ջնջել"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Էկրանի տեսագրումը չեղարկվեց"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Էկրանի տեսագրությունը պահվեց։ Հպեք՝ դիտելու համար:"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Էկրանի տեսագրությունը ջնջվեց"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Չհաջողվեց ջնջել տեսագրությունը"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Չհաջողվեց ստանալ անհրաժեշտ թույլտվությունները"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Չհաջողվեց սկսել տեսագրումը"</string>
@@ -337,7 +335,7 @@
<string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"Էկրանը կողպված է ուղղաձիգ դիրքավորմամբ:"</string>
<string name="accessibility_rotation_lock_off_changed" msgid="5772498370935088261">"Էկրանն այժմ ավտոմատ կպտտվի:"</string>
<string name="accessibility_rotation_lock_on_landscape_changed" msgid="5785739044300729592">"Էկրանն այժմ կողպված է հորիզոնական դիրքում:"</string>
- <string name="accessibility_rotation_lock_on_portrait_changed" msgid="5580170829728987989">"Էկրանն այժմ կողպված է ուղղահայաց դիրքում:"</string>
+ <string name="accessibility_rotation_lock_on_portrait_changed" msgid="5580170829728987989">"Էկրանն այժմ կողպված է ուղղաձիգ դիրքում:"</string>
<string name="dessert_case" msgid="9104973640704357717">"Dessert Case"</string>
<string name="start_dreams" msgid="9131802557946276718">"Էկրանապահ"</string>
<string name="ethernet_label" msgid="2203544727007463351">"Ethernet"</string>
@@ -513,7 +511,7 @@
<string name="notification_section_header_incoming" msgid="850925217908095197">"Նոր"</string>
<string name="notification_section_header_gentle" msgid="6804099527336337197">"Անձայն"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"Ծանուցումներ"</string>
- <string name="notification_section_header_conversations" msgid="821834744538345661">"Խոսակցություններ"</string>
+ <string name="notification_section_header_conversations" msgid="821834744538345661">"Զրույցներ"</string>
<string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"Ջնջել բոլոր անձայն ծանուցումները"</string>
<string name="dnd_suppressing_shade_text" msgid="5588252250634464042">"Ծանուցումները չեն ցուցադրվի «Չանհանգստացնել» ռեժիմում"</string>
<string name="media_projection_action_text" msgid="3634906766918186440">"Սկսել հիմա"</string>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 9417d483bb62..ea0dd97c5b37 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Lanjutkan"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Batal"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Bagikan"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Hapus"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Rekaman layar dibatalkan"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Rekaman layar disimpan, ketuk untuk melihat"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Rekaman layar dihapus"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Error saat menghapus rekaman layar"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Gagal mendapatkan izin"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Terjadi error saat memulai perekaman layar"</string>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 379666906f11..f185c193c952 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Halda áfram"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Hætta við"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Deila"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Eyða"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Hætt við skjáupptöku"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Skjáupptaka vistuð, ýttu til að skoða"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Skjáupptöku eytt"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Villa við að eyða skjáupptöku"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Ekki tókst að fá heimildir"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Villa við að hefja upptöku skjás"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 7d7785caa866..af48e57063ba 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Riprendi"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Annulla"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Condividi"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"CANC"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Registrazione dello schermo annullata"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Registrazione dello schermo salvata. Tocca per visualizzarla."</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Registrazione dello schermo eliminata"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Errore durante l\'eliminazione della registrazione dello schermo"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Impossibile ottenere le autorizzazioni"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Errore durante l\'avvio della registrazione dello schermo"</string>
@@ -716,7 +714,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Può suonare o vibrare in base alle impostazioni del telefono"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Può suonare o vibrare in base alle impostazioni del telefono. Conversazioni dalla bolla <xliff:g id="APP_NAME">%1$s</xliff:g> per impostazione predefinita."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantiene la tua attenzione con una scorciatoia mobile a questi contenuti."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Viene mostrata in cima alla sezione delle conversazioni, appare sotto forma di bolla mobile, mostra l\'immagine del profilo nella schermata di blocco"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Appare in cima alla sezione delle conversazioni e sotto forma di bolla mobile, mostra l\'immagine del profilo nella schermata di blocco"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Impostazioni"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Priorità"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> non supporta le funzionalità delle conversazioni"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 778ab9bbb873..29411a6e531f 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"המשך"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"ביטול"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"שיתוף"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"מחיקה"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"הקלטת המסך בוטלה"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"הקלטת המסך נשמרה, יש להקיש כדי להציג"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"הקלטת המסך נמחקה"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"שגיאה במחיקת הקלטת המסך"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"קבלת ההרשאות נכשלה"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"שגיאה בהפעלה של הקלטת המסך"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index ef80212874d8..a5a92b85630f 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"再開"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"キャンセル"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"共有"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"削除"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"画面の録画をキャンセルしました"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"画面の録画を保存しました。タップで表示できます"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"画面の録画を削除しました"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"画面の録画の削除中にエラーが発生しました"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"権限を取得できませんでした"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"画面の録画中にエラーが発生しました"</string>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index c2888117ca6b..f41f0b56625a 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"გაგრძელება"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"გაუქმება"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"გაზიარება"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"წაშლა"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"ეკრანის ჩაწერა გაუქმდა"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"ეკრანის ჩანაწერი შენახულია, შეეხეთ სანახავად"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"ეკრანის ჩანაწერი წაიშალა"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"ეკრანის ჩანაწერის წაშლისას წარმოიშვა შეცდომა"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"ნებართვების მიღება ვერ მოხერხდა"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"ეკრანის ჩაწერის დაწყებისას წარმოიქმნა შეცდომა"</string>
@@ -716,7 +714,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"დარეკვა ან ვიბრაცია ტელეფონის პარამეტრების მიხედვით"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"დარეკვა ან ვიბრაცია ტელეფონის პარამეტრების მიხედვით. მიმოწერები <xliff:g id="APP_NAME">%1$s</xliff:g>-ის ბუშტიდან, ნაგულისხმევად."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"იპყრობს თქვენს ყურადღებას ამ კონტენტის მოლივლივე მალსახმობით."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"გამოჩნდება მიმოწერების სექციის ზედა ნაწილში მოლივლივე ბუშტის სახით, აჩვენებს პროფილის სურათს ჩაკეტილ ეკრანზე"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"გამოჩნდება მიმოწერების ზედა ნაწილში ბუშტის სახით, აჩვენებს პროფილის სურათს ჩაკეტილ ეკრანზე"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"პარამეტრები"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"პრიორიტეტი"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g>-ს არ აქვს მიმოწერის ფუნქციების მხარდაჭერა"</string>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index 501e92e2de0b..1086f0ebdec5 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -28,7 +28,7 @@
<string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> қалды"</string>
<string name="battery_low_percent_format_hybrid" msgid="3985614339605686167">"Пайдалану барысына байланысты <xliff:g id="PERCENTAGE">%1$s</xliff:g> заряд, шамамен <xliff:g id="TIME">%2$s</xliff:g> қалды"</string>
<string name="battery_low_percent_format_hybrid_short" msgid="5917433188456218857">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> заряд, шамамен <xliff:g id="TIME">%2$s</xliff:g> қалды"</string>
- <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"<xliff:g id="PERCENTAGE">%s</xliff:g> қалды. Battery Saver қосулы."</string>
+ <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"<xliff:g id="PERCENTAGE">%s</xliff:g> қалды. Батареяны үнемдеу режимі қосулы."</string>
<string name="invalid_charger" msgid="4370074072117767416">"USB арқылы зарядтау мүмкін емес. Құрылғымен бірге берілген зарядтау құралын пайдаланыңыз."</string>
<string name="invalid_charger_title" msgid="938685362320735167">"USB арқылы зарядтау мүмкін емес"</string>
<string name="invalid_charger_text" msgid="2339310107232691577">"Құрылғымен бірге берілген зарядтау құралын пайдаланыңыз"</string>
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Жалғастыру"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Бас тарту"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Бөлісу"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Жою"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Экранды бейнеге жазудан бас тартылды"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Экран бейне жазбасы сақталды, көру үшін түртіңіз"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Экран бейне жазбасы жойылды"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Экран бейне жазбасын жою кезінде қате кетті"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Рұқсаттар алынбады"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Экрандағы бейнені жазу кезінде қате шықты."</string>
@@ -421,7 +419,7 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"<xliff:g id="TIME">%s</xliff:g> дейін"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"Қараңғы тақырып"</string>
- <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Battery Saver"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"Батареяны үнемдеу режимі"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"Күн батқанда қосу"</string>
<string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"Күн шыққанға дейін"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"Қосылу уақыты: <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -712,13 +710,13 @@
<string name="notification_alert_title" msgid="3656229781017543655">"Әдепкі"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"Көпіршік"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Дыбыс не діріл қолданылмайды"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Дыбыс не діріл қолданылмайды, төменде әңгімелер бөлімінде шығады"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Дыбыс не діріл қолданылмайды, әңгімелер бөлімінің төмен жағында шығады"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Телефон параметрлеріне байланысты шылдырлауы не дірілдеуі мүмкін"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Телефон параметрлеріне байланысты шылдырлауы не дірілдеуі мүмкін. <xliff:g id="APP_NAME">%1$s</xliff:g> чаттары әдепкісінше қалқымалы етіп көрсетіледі."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Осы мазмұнға бекітілген қалқымалы таңбашамен назарыңызды өзіне тартады."</string>
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Әңгімелер бөлімінің жоғарғы жағында тұрады, қалқыма хабар түрінде шығады, құлыптаулы экранда профиль суретін көрсетеді"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Параметрлер"</string>
- <string name="notification_priority_title" msgid="2079708866333537093">"Маңыздылығы"</string>
+ <string name="notification_priority_title" msgid="2079708866333537093">"Маңызды"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> әңгімелесу функцияларын қолдамайды."</string>
<string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Жақындағы қалқыма хабарлар жоқ"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Соңғы және жабылған қалқыма хабарлар осы жерде көрсетіледі."</string>
@@ -768,7 +766,7 @@
</plurals>
<string name="battery_panel_title" msgid="5931157246673665963">"Батареяны пайдалану"</string>
<string name="battery_detail_charging_summary" msgid="8821202155297559706">"Зарядтау кезінде Батарея үнемдегіш қол жетімді емес"</string>
- <string name="battery_detail_switch_title" msgid="6940976502957380405">"Battery Saver"</string>
+ <string name="battery_detail_switch_title" msgid="6940976502957380405">"Батареяны үнемдеу режимі"</string>
<string name="battery_detail_switch_summary" msgid="3668748557848025990">"Өнімділікті және фондық деректерді азайтады"</string>
<string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> түймесі"</string>
<string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 1ddca55e9aa8..fc27dd7198b7 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"បន្ត"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"បោះបង់"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"ចែករំលែក"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"លុប"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"បាន​បោះបង់​ការថត​សកម្មភាព​អេក្រង់"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"បានរក្សាទុក​ការថត​សកម្មភាព​អេក្រង់។ សូមចុច​ដើម្បី​មើល"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"បានលុប​ការថត​សកម្មភាព​អេក្រង់"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"មានបញ្ហា​ក្នុងការ​លុបការថត​សកម្មភាព​អេក្រង់"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"មិនអាច​ទទួលបាន​ការអនុញ្ញាត​ទេ"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"មានបញ្ហា​ក្នុងការ​ចាប់ផ្ដើម​ថត​អេក្រង់"</string>
@@ -421,7 +419,7 @@
<string name="quick_settings_night_secondary_label_on_at" msgid="3584738542293528235">"បើក​នៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_secondary_label_until" msgid="1883981263191927372">"រហូតដល់​ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="quick_settings_ui_mode_night_label" msgid="1398928270610780470">"រចនាប័ទ្ម​ងងឹត"</string>
- <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"កម្មវិធីសន្សំថ្ម"</string>
+ <string name="quick_settings_dark_mode_secondary_label_battery_saver" msgid="4990712734503013251">"មុខងារ​សន្សំ​ថ្ម"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at_sunset" msgid="6017379738102015710">"បើក​នៅពេល​ថ្ងៃលិច"</string>
<string name="quick_settings_dark_mode_secondary_label_until_sunrise" msgid="4404885070316716472">"រហូត​ដល់​ពេល​ថ្ងៃរះ"</string>
<string name="quick_settings_dark_mode_secondary_label_on_at" msgid="5128758823486361279">"បើកនៅម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
@@ -768,7 +766,7 @@
</plurals>
<string name="battery_panel_title" msgid="5931157246673665963">"ការប្រើប្រាស់ថ្ម"</string>
<string name="battery_detail_charging_summary" msgid="8821202155297559706">"កម្មវិធីសន្សំថ្មមិនអាចប្រើបានអំឡុងពេលសាកថ្មទេ"</string>
- <string name="battery_detail_switch_title" msgid="6940976502957380405">"កម្មវិធីសន្សំថ្ម"</string>
+ <string name="battery_detail_switch_title" msgid="6940976502957380405">"មុខងារ​សន្សំ​ថ្ម"</string>
<string name="battery_detail_switch_summary" msgid="3668748557848025990">"កាត់បន្ថយប្រតិបត្តិការ និងទិន្នន័យផ្ទៃខាងក្រោយ"</string>
<string name="keyboard_key_button_template" msgid="8005673627272051429">"ប៊ូតុង <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index c726e00ce131..044ecda5230e 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ಮುಂದುವರಿಸಿ"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"ರದ್ದುಮಾಡಿ"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"ಹಂಚಿಕೊಳ್ಳಿ"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"ಅಳಿಸಿ"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಅನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಅನ್ನು ಉಳಿಸಲಾಗಿದೆ, ವೀಕ್ಷಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಅಳಿಸಲಾಗಿದೆ"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಅಳಿಸುವಾಗ ದೋಷ ಕಂಡುಬಂದಿದೆ"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"ಅನುಮತಿಗಳನ್ನು ಪಡೆಯುವಲ್ಲಿ ವಿಫಲವಾಗಿದೆ"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"ಸ್ಕ್ರೀನ್ ರೆಕಾರ್ಡಿಂಗ್ ಪ್ರಾರಂಭಿಸುವಾಗ ದೋಷ ಕಂಡುಬಂದಿದೆ"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 9f8aafdf911f..b7e8581c2010 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"재개"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"취소"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"공유"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"삭제"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"화면 녹화가 취소되었습니다."</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"화면 녹화본이 저장되었습니다. 확인하려면 탭하세요."</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"화면 녹화가 삭제되었습니다."</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"화면 녹화는 삭제하는 중에 오류가 발생했습니다."</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"권한을 확보하지 못했습니다."</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"화면 녹화 시작 중 오류 발생"</string>
@@ -716,7 +714,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"휴대전화 설정에 따라 벨소리나 진동이 울릴 수 있음"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"휴대전화 설정에 따라 벨소리나 진동이 울릴 수 있습니다. 기본적으로 <xliff:g id="APP_NAME">%1$s</xliff:g>의 대화는 대화창으로 표시됩니다."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"이 콘텐츠로 연결되는 플로팅 바로가기로 사용자의 주의를 끕니다."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"대화 섹션 상단에 표시, 플로팅 대화창으로 표시, 그리고 잠금 화면에 프로필 사진이 표시됩니다."</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"대화 섹션 상단에 표시, 플로팅 대화창으로 표시, 그리고 잠금 화면에 프로필 사진이 표시됨"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"설정"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"우선순위"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> 앱은 대화 기능을 지원하지 않습니다."</string>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 134d04d3f702..d7390d07c313 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Улантуу"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Жокко чыгаруу"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Бөлүшүү"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Ооба"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Экранды жаздыруу жокко чыгарылды"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Экранды жаздыруу сакталды, көрүү үчүн таптап коюңуз"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Экранды жаздыруу өчүрүлдү"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Экранды жаздырууну өчүрүүдө ката кетти"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Уруксаттар алынбай калды"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Экранды жаздырууну баштоодо ката кетти"</string>
@@ -716,7 +714,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Телефондун жөндөөлөрүнө жараша шыңгырап же дирилдеши мүмкүн"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Телефондун жөндөөлөрүнө жараша шыңгырап же дирилдеши мүмкүн. <xliff:g id="APP_NAME">%1$s</xliff:g> колдонмосундагы жазышуулар демейки жөндөө боюнча калкып чыкма билдирмелер түрүндө көрүнөт."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Калкыма ыкчам баскыч менен көңүлүңүздү бул мазмунга буруп турат."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Жазышуу бөлүмүнүн жогорку жагында калкып чыкма билдирме түрүндө көрүнүп, профиль сүрөтү кулпуланган экрандан чагылдырылат"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Жазышуулар тизмесинин өйдө жагында калкып чыкма билдирме түрүндө көрүнүп, профиль сүрөтү кулпуланган экрандан чагылдырылат"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Жөндөөлөр"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Маанилүүлүгү"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> жазышуу функцияларын колдоого албайт"</string>
@@ -856,7 +854,7 @@
<string name="left_icon" msgid="5036278531966897006">"¨Солго¨ сүрөтчөсү"</string>
<string name="right_icon" msgid="1103955040645237425">"¨Оңго¨ сүрөтчөсү"</string>
<string name="drag_to_add_tiles" msgid="8933270127508303672">"Керектүү элементтерди сүйрөп келиңиз"</string>
- <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Элементтердин иретин өзгөртүү үчүн, кармап туруп, сүйрөңүз"</string>
+ <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"Элементтердин иретин өзгөртүү үчүн кармап туруп, сүйрөңүз"</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"Алып салуу үчүн бул жерге сүйрөңүз"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"Сизге жок дегенде <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> мозаика керек"</string>
<string name="qs_edit" msgid="5583565172803472437">"Түзөтүү"</string>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 9e1b66f07758..b584dfee1e60 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -47,4 +47,15 @@
<dimen name="global_actions_power_dialog_item_height">130dp</dimen>
<dimen name="global_actions_power_dialog_item_bottom_margin">35dp</dimen>
+
+ <dimen name="controls_management_top_padding">12dp</dimen>
+ <dimen name="controls_management_titles_margin">8dp</dimen>
+ <dimen name="controls_management_indicator_top_margin">8dp</dimen>
+ <dimen name="controls_management_list_margin">4dp</dimen>
+ <dimen name="controls_management_footer_height">56dp</dimen>
+ <dimen name="controls_management_zone_top_margin">24dp</dimen>
+
+ <!-- (footer_height -48dp)/2 -->
+ <dimen name="controls_management_footer_top_margin">4dp</dimen>
+ <dimen name="controls_management_favorites_top_margin">8dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 862e1458937d..14cd2113da6d 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ສືບຕໍ່"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"ຍົກເລີກ"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"ແບ່ງປັນ"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"ລຶບ"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"ຍົກເລີກການບັນທຶກໜ້າຈໍແລ້ວ"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"ຈັດເກັບການບັນທຶກໜ້າຈໍ, ແຕະເພື່ອເບິ່ງ"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"ລຶບການບັນທຶກໜ້າຈໍອອກແລ້ວ"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"ເກີດຄວາມຜິດພາດໃນການລຶບການບັນທຶກໜ້າຈໍ"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"ໂຫຼດສິດອະນຸຍາດບໍ່ສຳເລັດ"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"ເກີດຄວາມຜິດພາດໃນການບັນທຶກໜ້າຈໍ"</string>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index e50ceaf023c3..4aa16727cff7 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Tęsti"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Atšaukti"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Bendrinti"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Ištrinti"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Ekrano įrašymas atšauktas"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Ekrano įrašas išsaugotas, palieskite ir peržiūrėkite"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Ekrano įrašas ištrintas"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Ištrinant ekrano įrašą įvyko klaida"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Nepavyko gauti leidimų"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Pradedant ekrano vaizdo įrašymą iškilo problema"</string>
@@ -778,7 +776,7 @@
</plurals>
<string name="battery_panel_title" msgid="5931157246673665963">"Akum. energ. vartoj."</string>
<string name="battery_detail_charging_summary" msgid="8821202155297559706">"Akumuliatoriaus tausojimo priemonė nepasiekiama įkraunant"</string>
- <string name="battery_detail_switch_title" msgid="6940976502957380405">"Akumuliat. taus. pr."</string>
+ <string name="battery_detail_switch_title" msgid="6940976502957380405">"Akum. taus. pr."</string>
<string name="battery_detail_switch_summary" msgid="3668748557848025990">"Sumažinamas našumas ir foninių duomenų naudojimas"</string>
<string name="keyboard_key_button_template" msgid="8005673627272051429">"Mygtukas <xliff:g id="NAME">%1$s</xliff:g>"</string>
<string name="keyboard_key_home" msgid="3734400625170020657">"Pagrindinis"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index d05fa08f1bbe..1ef1233989ac 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Atsākt"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Atcelt"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Kopīgot"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Dzēst"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Ekrāna ierakstīšana ir atcelta."</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Ekrāna ieraksts ir saglabāts. Pieskarieties, lai to skatītu."</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Ekrāna ieraksts ir izdzēsts."</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Dzēšot ekrāna ierakstu, radās kļūda."</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Neizdevās iegūt atļaujas."</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Sākot ierakstīt ekrāna saturu, radās kļūda."</string>
@@ -715,7 +713,7 @@
<string name="notification_alert_title" msgid="3656229781017543655">"Noklusējums"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"Burbulis"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Nav skaņas signāla vai vibrācijas"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Nav skaņas signāla vai vibrācijas, kā arī atrodas zemāk sarunu sadaļā"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Nav skaņas signāla vai vibrācijas, kā arī atrodas tālāk sarunu sadaļā"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Atkarībā no tālruņa iestatījumiem var zvanīt vai vibrēt"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Atkarībā no tālruņa iestatījumiem var zvanīt vai vibrēt. Sarunas no lietotnes <xliff:g id="APP_NAME">%1$s</xliff:g> pēc noklusējuma tiek parādītas burbulī."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Piesaista jūsu uzmanību, rādot peldošu saīsni uz šo saturu."</string>
diff --git a/packages/SystemUI/res/values-mcc310-mnc004/strings.xml b/packages/SystemUI/res/values-mcc310-mnc004/strings.xml
new file mode 100644
index 000000000000..f8ed0c01fa83
--- /dev/null
+++ b/packages/SystemUI/res/values-mcc310-mnc004/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SystemUI/res/values-mcc311-mnc480/strings.xml b/packages/SystemUI/res/values-mcc311-mnc480/strings.xml
new file mode 100644
index 000000000000..f8ed0c01fa83
--- /dev/null
+++ b/packages/SystemUI/res/values-mcc311-mnc480/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Content description of the data connection type 5G UW. [CHAR LIMIT=NONE] -->
+ <string name="data_connection_5g_plus" translatable="false">5G UW</string>
+</resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 0fde26167d67..4f6d8244039a 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Продолжи"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Откажи"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Сподели"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Избриши"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Снимањето екран е откажано"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Снимката од екранот е зачувана, допрете за да ја видите"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Снимката од екранот е избришана"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Грешка при бришењето на снимката од екранот"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Не успеаја да се добијат дозволи"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Грешка при почетокот на снимањето на екранот"</string>
@@ -712,13 +710,13 @@
<string name="notification_alert_title" msgid="3656229781017543655">"Стандардно"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"Балонче"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Без звук или вибрации"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Без звук или вибрации и се појавува под делот за разговор"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Без звук или вибрации и се појавува подолу во делот со разговори"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Може да ѕвони или вибрира во зависност од поставките на телефонот"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Може да ѕвони или вибрира во зависност од поставките на телефонот Стандардно, разговорите од <xliff:g id="APP_NAME">%1$s</xliff:g> се во балончиња."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Ви го задржува вниманието со лебдечка кратенка на содржинава."</string>
<string name="notification_channel_summary_priority" msgid="7952654515769021553">"Се појавува на горниот дел од секцијата на разговорот во вид на лебдечко меурче, покажувајќи ја профилната слика на заклучениот екран"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Поставки"</string>
- <string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
+ <string name="notification_priority_title" msgid="2079708866333537093">"Приоритетно"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> не поддржува функции за разговор"</string>
<string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Нема неодамнешни балончиња"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Неодамнешните и отфрлените балончиња ќе се појавуваат тука"</string>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 9624be9430a2..277169e2f630 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"പുനരാരംഭിക്കുക"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"റദ്ദാക്കുക"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"പങ്കിടുക"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"ഇല്ലാതാക്കുക"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"സ്ക്രീൻ റെക്കോർഡിംഗ് റദ്ദാക്കി"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"സ്ക്രീൻ റെക്കോർഡിംഗ് സംരക്ഷിച്ചു, കാണാൻ ടാപ്പ് ചെയ്യുക"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"സ്ക്രീൻ റെക്കോർഡിംഗ് ഇല്ലാതാക്കി"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"സ്ക്രീൻ റെക്കോർഡിംഗ് ഇല്ലാതാക്കുന്നതിൽ പിശക്"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"അനുമതികൾ ലഭിച്ചില്ല"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"സ്ക്രീൻ റെക്കോർഡിംഗ് ആരംഭിക്കുന്നതിൽ പിശക്"</string>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 59305949d529..4f040fa33ec4 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Үргэлжлүүлэх"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Цуцлах"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Хуваалцах"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Устгах"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Дэлгэцийн бичлэгийг цуцалсан"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Дэлгэцийн бичлэгийг хадгалсан. Харахын тулд товшино уу"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Дэлгэцийн бичлэгийг устгасан"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Дэлгэцийн бичлэгийг устгахад алдаа гарлаа"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Зөвшөөрөл авч чадсангүй"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Дэлгэцийн бичлэгийг эхлүүлэхэд алдаа гарлаа"</string>
@@ -712,7 +710,7 @@
<string name="notification_alert_title" msgid="3656229781017543655">"Өгөгдмөл"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"Бөмбөлөг"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Дуу эсвэл чичиргээ байхгүй"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Дуу эсвэл чичиргээ байхгүй бөгөөд харицан ярианы хэсгийн доод талд харагдана"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Дуу эсвэл чичиргээ байхгүй бөгөөд харилцан ярианы хэсгийн доод талд харагдана"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Утасны тохиргоонд тулгуурлан хонх дуугаргах эсвэл чичирхийлж болзошгүй"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Утасны тохиргоонд тулгуурлан хонх дуугаргах эсвэл чичирхийлж болзошгүй. <xliff:g id="APP_NAME">%1$s</xliff:g>-н харилцан яриаг өгөгдмөл тохиргооны дагуу бөмбөлөг болгоно."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Энэ контентын хөвөн гарч ирэх товчлолтойгоор таны анхаарлыг татдаг."</string>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 3c87b3136ee8..6bbf77f781f0 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"पुन्हा सुरू करा"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"रद्द करा"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"शेअर करा"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"हटवा"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"स्क्रीन रेकॉर्डिंग रद्द केले"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"स्क्रीन रेकॉर्डिंग सेव्ह केली, पाहण्यासाठी टॅप करा"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"स्क्रीन रेकॉर्डिंग हटवले"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"स्क्रीन रेकॉर्डिंग हटवताना एरर आली"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"परवानग्या मिळवता आल्या नाहीत"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"स्क्रीन रेकॉर्डिंग सुरू करताना एरर आली"</string>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index f72e3ef75607..b16427624cc6 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Sambung semula"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Batal"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Kongsi"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Padam"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Rakaman skrin dibatalkan"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Rakaman skrin disimpan, ketik untuk melihat"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Rakaman skrin dipadamkan"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Ralat semasa memadamkan rakaman skrin"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Gagal mendapatkan kebenaran"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Ralat semasa memulakan rakaman skrin"</string>
@@ -405,7 +403,7 @@
<item quantity="one">%d peranti</item>
</plurals>
<string name="quick_settings_notifications_label" msgid="3379631363952582758">"Pemberitahuan"</string>
- <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lampu suluh"</string>
+ <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lampu Suluh"</string>
<string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Kamera sedang digunakan"</string>
<string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Data mudah alih"</string>
<string name="quick_settings_cellular_detail_data_usage" msgid="6105969068871138427">"Penggunaan data"</string>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 8f5b47e9fbcf..6d71f1d5fcdd 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ဆက်လုပ်ရန်"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"မလုပ်တော့"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"မျှဝေရန်"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"ဖျက်ရန်"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"ဖန်သားပြင် ရိုက်ကူးမှု ပယ်ဖျက်လိုက်ပါပြီ"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"ဖန်သားပြင် ရိုက်ကူးမှု သိမ်းထားသည်၊ ကြည့်ရန် တို့ပါ"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"ဖန်သားပြင် ရိုက်ကူးမှု ဖျက်ပြီးပါပြီ"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"ဖန်သားပြင် ရိုက်ကူးမှု ဖျက်ရာတွင် အမှားအယွင်းရှိနေသည်"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"ခွင့်ပြုချက် မရယူနိုင်ပါ"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"ဖန်သားပြင် ရိုက်ကူးမှု စတင်ရာတွင် အမှားအယွင်းရှိနေသည်"</string>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 56851e421dc7..14de00ae2c85 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Gjenoppta"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Avbryt"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Del"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Slett"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Skjermopptak er avbrutt"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Skjermopptaket er lagret. Trykk for å se det"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Skjermopptaket er slettet"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Feil ved sletting av skjermopptaket"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Kunne ikke få tillatelser"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Feil ved start av skjermopptaket"</string>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 61e500afeb4a..5739e9a459f7 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -43,7 +43,7 @@
<string name="status_bar_settings_mute_label" msgid="914392730086057522">"म्युट गर्नुहोस्"</string>
<string name="status_bar_settings_auto_brightness_label" msgid="2151934479226017725">"स्वतः"</string>
<string name="status_bar_settings_notifications" msgid="5285316949980621438">"सूचनाहरू"</string>
- <string name="bluetooth_tethered" msgid="4171071193052799041">"ब्लुटुथ टेथर भयो"</string>
+ <string name="bluetooth_tethered" msgid="4171071193052799041">"ब्लुटुथ टेदर भयो"</string>
<string name="status_bar_input_method_settings_configure_input_methods" msgid="2972273031043777851">"इनपुट विधिहरू सेटअप गर्नुहोस्"</string>
<string name="status_bar_use_physical_keyboard" msgid="4849251850931213371">"वास्तविक किबोर्ड"</string>
<string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_DEVICE">%2$s</xliff:g> माथि पहुँच राख्ने अनुमति दिने हो?"</string>
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"जारी राख्नुहोस्"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"रद्द गर्नुहोस्"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"सेयर गर्नुहोस्"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"मेट्नुहोस्"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"स्क्रिन रेकर्ड गर्ने कार्य रद्द गरियो"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"स्क्रिन रेकर्डिङ सुरक्षित गरियो, हेर्न ट्याप गर्नुहोस्‌"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"स्क्रिनको रेकर्डिङ मेटाइयो"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"स्क्रिनको रेकर्डिङ मेट्ने क्रममा त्रुटि"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"अनुमति प्राप्त गर्न सकिएन"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"स्क्रिन रेकर्ड गर्न थाल्ने क्रममा त्रुटि भयो"</string>
@@ -502,8 +500,8 @@
<string name="battery_saver_notification_title" msgid="8419266546034372562">"ब्याट्री सेभर अन छ"</string>
<string name="battery_saver_notification_text" msgid="2617841636449016951">"प्रदर्शन र पृष्ठभूमि डेटा घटाउँनुहोस्"</string>
<string name="battery_saver_notification_action_text" msgid="6022091913807026887">"ब्याट्री सेभर अफ गर्नुहोस्"</string>
- <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले तपाईंको स्क्रिनमा देख्न सकिने सबै जानकारी अथवा रेकर्ड वा cast गर्दा तपाईंको यन्त्रबाट प्ले गरिएका कुरामाथि पहुँच राख्न सक्ने छ। यसअन्तर्गत पासवर्ड, भुक्तानीका विवरण, तस्बिर, सन्देश र तपाईंले प्ले गर्ने अडियो जस्ता जानकारी समावेश हुन्छन्।"</string>
- <string name="media_projection_dialog_service_text" msgid="958000992162214611">"यो कार्य प्रदान गर्ने सेवाले तपाईंको स्क्रिनमा देख्न सकिने सबै जानकारी अथवा रेकर्ड वा cast गर्दा तपाईंको यन्त्रबाट प्ले गरिएका कुरामाथि पहुँच राख्न सक्ने छ। यसअन्तर्गत पासवर्ड, भुक्तानीका विवरण, तस्बिर, सन्देश र तपाईंले प्ले गर्ने अडियो जस्ता जानकारी समावेश हुन्छन्।"</string>
+ <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> ले तपाईंको स्क्रिनमा देख्न सकिने सबै जानकारी अथवा रेकर्ड वा cast गर्दा तपाईंको यन्त्रबाट प्ले गरिएका कुरामाथि पहुँच राख्न सक्ने छ। यसअन्तर्गत पासवर्ड, भुक्तानीका विवरण, फोटो, सन्देश र तपाईंले प्ले गर्ने अडियो जस्ता जानकारी समावेश हुन्छन्।"</string>
+ <string name="media_projection_dialog_service_text" msgid="958000992162214611">"यो कार्य प्रदान गर्ने सेवाले तपाईंको स्क्रिनमा देख्न सकिने सबै जानकारी अथवा रेकर्ड वा cast गर्दा तपाईंको यन्त्रबाट प्ले गरिएका कुरामाथि पहुँच राख्न सक्ने छ। यसअन्तर्गत पासवर्ड, भुक्तानीका विवरण, फोटो, सन्देश र तपाईंले प्ले गर्ने अडियो जस्ता जानकारी समावेश हुन्छन्।"</string>
<string name="media_projection_dialog_service_title" msgid="2888507074107884040">"रेकर्ड गर्न वा cast गर्न थाल्ने हो?"</string>
<string name="media_projection_dialog_title" msgid="3316063622495360646">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g> मार्फत रेकर्ड गर्न वा cast गर्न थाल्ने हो?"</string>
<string name="media_projection_remember_text" msgid="6896767327140422951">"फेरि नदेखाउनुहोस्"</string>
@@ -716,7 +714,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"फोनको सेटिङका आधारमा घन्टी बज्न वा कम्पन हुन सक्छ"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"फोनको सेटिङका आधारमा घन्टी बज्न वा कम्पन हुन सक्छ। <xliff:g id="APP_NAME">%1$s</xliff:g> का वार्तालापहरू पूर्वनिर्धारित रूपमा बबलमा देखाइन्छन्।"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"फ्लोटिङ सर्टकटमार्फत यो सामग्रीतर्फ तपाईंको ध्यान आकर्षित गर्दछ।"</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"वार्तालाप खण्डको सिरानमा देखा पर्छ, तैरने बबलका रूपमा देखा पर्छ, लक स्क्रिनमा प्रोफाइल तस्बिर देखाइन्छ"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"वार्तालाप खण्डको सिरानमा देखा पर्छ, तैरने बबलका रूपमा देखा पर्छ, लक स्क्रिनमा प्रोफाइल फोटो देखाइन्छ"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"सेटिङ"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"प्राथमिकता"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> मा वार्तालापसम्बन्धी सुविधा प्रयोग गर्न मिल्दैन"</string>
@@ -1026,7 +1024,7 @@
<string name="priority_onboarding_title" msgid="2893070698479227616">"वार्तालापको प्राथमिकता निर्धारण गरी \"महत्त्वपूर्ण\" बनाइयो"</string>
<string name="priority_onboarding_behavior" msgid="5342816047020432929">"महत्वपूर्ण वार्तालापहरू:"</string>
<string name="priority_onboarding_show_at_top_text" msgid="1678400241025513541">"वार्तालाप खण्डको सिरानमा देखिने छन्"</string>
- <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"लक स्क्रिनमा प्रोफाइल तस्बिर देखाउने छन्"</string>
+ <string name="priority_onboarding_show_avatar_text" msgid="5756291381124091508">"लक स्क्रिनमा प्रोफाइल फोटो देखाउने छन्"</string>
<string name="priority_onboarding_appear_as_bubble_text" msgid="4227039772250263122">"एपहरूमाथि तैरिने बबलका रूपमा देखाइयोस्"</string>
<string name="priority_onboarding_ignores_dnd_text" msgid="2918952762719600529">"बाधा नपुऱ्याउनुहोस् मोडलाई बेवास्ता गरियोस्"</string>
<string name="priority_onboarding_done_button_title" msgid="4569550984286506007">"बुझेँ"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index dfe41df5c340..df93cab8cd46 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Hervatten"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Annuleren"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Delen"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Verwijderen"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Schermopname geannuleerd"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Schermopname opgeslagen, tik om te bekijken"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Schermopname verwijderd"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Fout bij verwijderen van schermopname"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Kan rechten niet ophalen"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Fout bij starten van schermopname"</string>
@@ -392,7 +390,7 @@
<string name="quick_settings_inversion_label" msgid="5078769633069667698">"Kleuren omkeren"</string>
<string name="quick_settings_color_space_label" msgid="537528291083575559">"Modus voor kleurcorrectie"</string>
<string name="quick_settings_more_settings" msgid="2878235926753776694">"Meer instellingen"</string>
- <string name="quick_settings_done" msgid="2163641301648855793">"Gereed"</string>
+ <string name="quick_settings_done" msgid="2163641301648855793">"Klaar"</string>
<string name="quick_settings_connected" msgid="3873605509184830379">"Verbonden"</string>
<string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"Verbonden, batterij <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
<string name="quick_settings_connecting" msgid="2381969772953268809">"Verbinding maken…"</string>
@@ -694,7 +692,7 @@
<string name="notification_channel_silenced" msgid="1995937493874511359">"Deze meldingen worden zonder geluid weergegeven"</string>
<string name="notification_channel_unsilenced" msgid="94878840742161152">"Deze meldingen stellen je op de hoogte"</string>
<string name="inline_blocking_helper" msgid="2891486013649543452">"Meestal sluit je deze meldingen. \nWil je ze blijven weergeven?"</string>
- <string name="inline_done_button" msgid="6043094985588909584">"Gereed"</string>
+ <string name="inline_done_button" msgid="6043094985588909584">"Klaar"</string>
<string name="inline_ok_button" msgid="603075490581280343">"Toepassen"</string>
<string name="inline_keep_showing" msgid="8736001253507073497">"Deze meldingen blijven weergeven?"</string>
<string name="inline_stop_button" msgid="2453460935438696090">"Meldingen stoppen"</string>
@@ -712,11 +710,11 @@
<string name="notification_alert_title" msgid="3656229781017543655">"Standaard"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"Bubbel"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Geen geluid of trilling"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Geen geluid of trilling en wordt op een lagere positie in het gedeelte met gesprekken weergegeven"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"Geen geluid of trilling en wordt lager in het gedeelte met gesprekken weergegeven"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Kan overgaan of trillen op basis van de telefooninstellingen"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Kan overgaan of trillen op basis van de telefooninstellingen. Gesprekken uit <xliff:g id="APP_NAME">%1$s</xliff:g> worden standaard als bubbels weergegeven."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Trekt de aandacht met een zwevende snelkoppeling naar deze content."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wordt bovenaan het gedeelte met gesprekken weergegeven, verschijnt als zwevende bubbel, geeft de profielfoto weer op het vergrendelscherm"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Wordt bovenaan het gespreksgedeelte weergegeven, verschijnt als zwevende bubbel, geeft profielfoto weer op vergrendelscherm"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Instellingen"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioriteit"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ondersteunt geen gespreksfuncties"</string>
@@ -741,7 +739,7 @@
<string name="notification_channel_switch_accessibility" msgid="8979885820432540252">"Meldingen van dit kanaal toestaan"</string>
<string name="notification_more_settings" msgid="4936228656989201793">"Meer instellingen"</string>
<string name="notification_app_settings" msgid="8963648463858039377">"Aanpassen"</string>
- <string name="notification_done" msgid="6215117625922713976">"Gereed"</string>
+ <string name="notification_done" msgid="6215117625922713976">"Klaar"</string>
<string name="inline_undo" msgid="9026953267645116526">"Ongedaan maken"</string>
<string name="demote" msgid="6225813324237153980">"Deze melding markeren als geen gesprek"</string>
<string name="notification_conversation_favorite" msgid="1905240206975921907">"Belangrijk gesprek"</string>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index 6ab0791ad9c8..e92217600116 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ପୁଣି ଚାଲୁ କରନ୍ତୁ"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"ବାତିଲ୍‌ କରନ୍ତୁ"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"ସେୟାର୍‍ କରନ୍ତୁ"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"ଡିଲିଟ୍ କରନ୍ତୁ"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"ସ୍କ୍ରିନ୍‍ ରେକର୍ଡିଂ ବାତିଲ୍‌ କରିଦିଆଯାଇଛି"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"ସ୍କ୍ରିନ୍‍ ରେକର୍ଡିଂ ସେଭ୍‍ ହୋଇଛି, ଦେଖିବାକୁ ଟାପ୍‍ କରନ୍ତୁ"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"ସ୍କ୍ରିନ୍‍ ରେକର୍ଡିଂ ଡିଲିଟ୍‍ କରିଦିଆଯାଇଛି"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"ସ୍କ୍ରିନ୍‍ ରେକର୍ଡିଂ ଡିଲିଟ୍‍ କରିବାରେ ତ୍ରୁଟି"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"ଅନୁମତି ପାଇବାରେ ଅସଫଳ ହେଲା।"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"ସ୍କ୍ରିନ୍ ରେକର୍ଡିଂ ଆରମ୍ଭ କରିବାରେ ତ୍ରୁଟି"</string>
@@ -716,7 +714,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"ଫୋନ୍ ସେଟିଂସ୍ ଆଧାରରେ ରିଙ୍ଗ କିମ୍ବା ଭାଇବ୍ରେଟ୍ ହୋଇପାରେ"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"ଫୋନ୍ ସେଟିଂସ୍ ଆଧାରରେ ରିଙ୍ଗ କିମ୍ବା ଭାଇବ୍ରେଟ୍ ହୋଇପାରେ। <xliff:g id="APP_NAME">%1$s</xliff:g>ରୁ ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ଡିଫଲ୍ଟ ଭାବରେ ବବଲ୍ ହୁଏ।"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"ଏହି ବିଷୟବସ୍ତୁ ପାଇଁ ଏକ ଭାସମାନ ସର୍ଟକଟ୍ ସହ ଆପଣଙ୍କର ଧ୍ୟାନ ଦିଅନ୍ତୁ।"</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"ବାର୍ତ୍ତାଳାପ ବିଭାଗର ଶୀର୍ଷରେ ଦେଖାଏ, ଭାସମାନ ବବଲ୍ ଭାବେ ଦେଖାଯାଏ, ଲକ୍ ସ୍କ୍ରିନରେ ପ୍ରୋଫାଇଲ୍ ଛବି ଡିସପ୍ଲେ କରେ"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"ବାର୍ତ୍ତାଳାପ ବିଭାଗର ଶୀର୍ଷରେ ଦେଖାଏ, ଫ୍ଲୋଟିଂ ବବଲ୍ ଭାବେ ଦେଖାଯାଏ, ଲକ୍ ସ୍କ୍ରିନରେ ପ୍ରୋଫାଇଲ୍ ଛବି ଡିସପ୍ଲେ କରେ"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"ସେଟିଂସ୍"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"ପ୍ରାଥମିକତା"</string>
<string name="no_shortcut" msgid="8257177117568230126">"<xliff:g id="APP_NAME">%1$s</xliff:g> ବାର୍ତ୍ତାଳାପ ଫିଚରଗୁଡ଼ିକୁ ସମର୍ଥନ କରେ ନାହିଁ"</string>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 2e481f53963b..a3bc4e0644ae 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ਮੁੜ-ਚਾਲੂ ਕਰੋ"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"ਰੱਦ ਕਰੋ"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"ਸਾਂਝਾ ਕਰੋ"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"ਮਿਟਾਓ"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"ਸਕ੍ਰੀਨ ਦੀ ਰਿਕਾਰਡਿੰਗ ਰੱਦ ਕੀਤੀ ਗਈ"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਰੱਖਿਅਤ ਕੀਤੀ ਗਈ, ਦੇਖਣ ਲਈ ਟੈਪ ਕਰੋ"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਨੂੰ ਮਿਟਾਇਆ ਗਿਆ"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਨੂੰ ਮਿਟਾਉਣ ਦੌਰਾਨ ਗੜਬੜ ਹੋਈ"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"ਇਜਾਜ਼ਤਾਂ ਪ੍ਰਾਪਤ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"ਸਕ੍ਰੀਨ ਰਿਕਾਰਡਿੰਗ ਨੂੰ ਸ਼ੁਰੂ ਕਰਨ ਵੇਲੇ ਗੜਬੜ ਹੋਈ"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index d946f9a4fbb4..5d7a6a18acb4 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Wznów"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Anuluj"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Udostępnij"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Usuń"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Anulowano nagrywanie zawartości ekranu"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Zapisano nagranie zawartości ekranu – kliknij, by je obejrzeć"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Usunięto nagranie zawartości ekranu"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Błąd podczas usuwania nagrania zawartości ekranu"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Nie udało się uzyskać uprawnień"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Błąd podczas rozpoczynania rejestracji zawartości ekranu"</string>
@@ -1023,7 +1021,7 @@
<string name="bubble_accessibility_action_move_bottom_left" msgid="6339015902495504715">"Przenieś w lewy dolny róg"</string>
<string name="bubble_accessibility_action_move_bottom_right" msgid="7471571700628346212">"Przenieś w prawy dolny róg"</string>
<string name="bubble_dismiss_text" msgid="1314082410868930066">"Zamknij dymek"</string>
- <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nie wyświetlaj rozmowy jako dymku"</string>
+ <string name="bubbles_dont_bubble_conversation" msgid="1033040343437428822">"Nie wyświetlaj rozmowy jako dymka"</string>
<string name="bubbles_user_education_title" msgid="5547017089271445797">"Czatuj, korzystając z dymków"</string>
<string name="bubbles_user_education_description" msgid="1160281719576715211">"Nowe rozmowy będą wyświetlane jako pływające ikony lub dymki. Kliknij, by otworzyć dymek. Przeciągnij, by go przenieść."</string>
<string name="bubbles_user_education_manage_title" msgid="2848511858160342320">"Zarządzaj dymkami w dowolnym momencie"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 9c0db7a4e71d..b23fba93fab6 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancelar"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Compartilhar"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Excluir"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Gravação de tela cancelada"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Gravação de tela salva, toque para ver"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Gravação de tela excluída"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Erro ao excluir a gravação de tela"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Não foi possível acessar as permissões"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Erro ao iniciar a gravação de tela"</string>
@@ -713,12 +711,12 @@
<string name="notification_bubble_title" msgid="8330481035191903164">"Bolha"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Som e vibração desativados"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"O som e a vibração estão desativados, e o balão aparece na parte inferior da seção de conversa"</string>
- <string name="notification_channel_summary_default" msgid="3282930979307248890">"Pode vibrar ou tocar com base nas configurações do smartphone"</string>
+ <string name="notification_channel_summary_default" msgid="3282930979307248890">"Podem vibrar ou tocar com base nas configurações do smartphone"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode vibrar ou tocar com base nas configurações do smartphone. As conversas do app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem em balões por padrão."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém sua atenção com um atalho flutuante para esse conteúdo."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece na parte superior de uma seção de conversa, em forma de balão, mostrando a foto do perfil na tela de bloqueio"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparecem na parte superior de uma seção de conversa, em forma de balões, mostrando a foto do perfil na tela de bloqueio"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configurações"</string>
- <string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
+ <string name="notification_priority_title" msgid="2079708866333537093">"Prioritárias"</string>
<string name="no_shortcut" msgid="8257177117568230126">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com recursos de conversa"</string>
<string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Nenhum balão recente"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Os balões recentes e dispensados aparecerão aqui"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 478d8fdd644c..a961565df91c 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancelar"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Partilhar"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Eliminar"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Gravação de ecrã cancelada."</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Gravação de ecrã guardada. Toque para ver."</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Gravação de ecrã eliminada."</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Erro ao eliminar a gravação de ecrã."</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Falha ao obter as autorizações."</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Ocorreu um erro ao iniciar a gravação do ecrã."</string>
@@ -716,7 +714,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Pode tocar ou vibrar com base nas definições do telemóvel."</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode tocar ou vibrar com base nas definições do telemóvel. As conversas da app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem como um balão por predefinição."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém a sua atenção com um atalho flutuante para este conteúdo."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece na parte superior da secção de conversas, surge como um balão flutuante e apresenta a imagem do perfil no ecrã de bloqueio."</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece no topo da secção de conversas, surge como balão flutuante e apresenta a imagem do perfil no ecrã de bloqueio."</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Definições"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
<string name="no_shortcut" msgid="8257177117568230126">"A app <xliff:g id="APP_NAME">%1$s</xliff:g> não suporta funcionalidades de conversa."</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 9c0db7a4e71d..b23fba93fab6 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Retomar"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Cancelar"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Compartilhar"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Excluir"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Gravação de tela cancelada"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Gravação de tela salva, toque para ver"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Gravação de tela excluída"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Erro ao excluir a gravação de tela"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Não foi possível acessar as permissões"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Erro ao iniciar a gravação de tela"</string>
@@ -713,12 +711,12 @@
<string name="notification_bubble_title" msgid="8330481035191903164">"Bolha"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"Som e vibração desativados"</string>
<string name="notification_conversation_summary_low" msgid="1734433426085468009">"O som e a vibração estão desativados, e o balão aparece na parte inferior da seção de conversa"</string>
- <string name="notification_channel_summary_default" msgid="3282930979307248890">"Pode vibrar ou tocar com base nas configurações do smartphone"</string>
+ <string name="notification_channel_summary_default" msgid="3282930979307248890">"Podem vibrar ou tocar com base nas configurações do smartphone"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Pode vibrar ou tocar com base nas configurações do smartphone. As conversas do app <xliff:g id="APP_NAME">%1$s</xliff:g> aparecem em balões por padrão."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Mantém sua atenção com um atalho flutuante para esse conteúdo."</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparece na parte superior de uma seção de conversa, em forma de balão, mostrando a foto do perfil na tela de bloqueio"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Aparecem na parte superior de uma seção de conversa, em forma de balões, mostrando a foto do perfil na tela de bloqueio"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Configurações"</string>
- <string name="notification_priority_title" msgid="2079708866333537093">"Prioridade"</string>
+ <string name="notification_priority_title" msgid="2079708866333537093">"Prioritárias"</string>
<string name="no_shortcut" msgid="8257177117568230126">"O app <xliff:g id="APP_NAME">%1$s</xliff:g> não é compatível com recursos de conversa"</string>
<string name="bubble_overflow_empty_title" msgid="3120029421991510842">"Nenhum balão recente"</string>
<string name="bubble_overflow_empty_subtitle" msgid="2030874469510497397">"Os balões recentes e dispensados aparecerão aqui"</string>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 54d6d5583bc0..12a622c8d90f 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Reluați"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Anulați"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Trimiteți"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Ștergeți"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Înregistrarea ecranului a fost anulată"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Înregistrarea ecranului a fost salvată. Atingeți pentru vizualizare"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Înregistrarea ecranului a fost ștearsă."</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Eroare la ștergerea înregistrării ecranului"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Nu s-au obținut permisiunile"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Eroare la începerea înregistrării ecranului"</string>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index a9bb44b79a97..b30afd61a0bb 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Возобновить"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Отмена"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Поделиться"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Удалить"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Запись видео с экрана отменена"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Запись видео с экрана сохранена. Чтобы открыть ее, нажмите на уведомление."</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Запись видео с экрана удалена"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Не удалось удалить запись видео с экрана"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Не удалось получить необходимые разрешения"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Не удалось начать запись видео с экрана."</string>
@@ -722,7 +720,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"Звонок или вибрация в зависимости от настроек телефона"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"Звонок или вибрация в зависимости от настроек телефона. Разговоры из приложения \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" по умолчанию появляются в виде всплывающего чата."</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"Привлекает ваше внимание к контенту с помощью плавающего ярлыка"</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Появляется в верхней части списка разговоров и как всплывающий чат, а также показывает фото профиля на заблокированном экране"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"Появляется в верхней части списка разговоров и как всплывающий чат, фото профиля показывается на заблок. экране"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"Настройки"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"Приоритет"</string>
<string name="no_shortcut" msgid="8257177117568230126">"Приложение \"<xliff:g id="APP_NAME">%1$s</xliff:g>\" не поддерживает функции разговоров."</string>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index fe3457b5f45a..2be74df2dc47 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"නැවත අරඹන්න"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"අවලංගු කරන්න"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"බෙදා ගන්න"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"මකන්න"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"තිර පටිගත කිරීම අවලංගු කරන ලදී"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"තිර පටිගත කිරීම සුරකින ලදී, බැලීමට තට්ටු කරන්න"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"තිර පටිගත කිරීම මකන ලදී"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"තිර පටිගත කිරීම මැකීමේ දෝෂයකි"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"අවසර ලබා ගැනීමට අසමත් විය"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"තිර පටිගත කිරීම ආරම්භ කිරීමේ දෝෂයකි"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index ae6154d8ef9a..001b4740e264 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Obnoviť"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Zrušiť"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Zdieľať"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Odstrániť"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Záznam obrazovky bol zrušený"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Záznam obrazovky bol uložený, zobrazíte ho klepnutím"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Záznam obrazovky bol odstránený"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Pri odstraňovaní záznamu obrazovky sa vyskytla chyba"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Nepodarilo sa získať povolenia"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Pri spustení nahrávania obrazovky sa vyskytla chyba"</string>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 8e9544edf7b1..4962435058db 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -95,7 +95,7 @@
<string name="screenrecord_description" msgid="1123231719680353736">"Med snemanjem lahko sistem Android zajame morebitne občutljive podatke, ki so prikazani na zaslonu ali se predvajajo v napravi. To vključuje gesla, podatke za plačilo, fotografije, sporočila in zvok."</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"Snemanje zvoka"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"Zvok v napravi"</string>
- <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvok v napravi, kot so glasba, klici in toni zvonjenja"</string>
+ <string name="screenrecord_device_audio_description" msgid="4922694220572186193">"Zvoki v napravi, kot so glasba, klici in toni zvonjenja"</string>
<string name="screenrecord_mic_label" msgid="2111264835791332350">"Mikrofon"</string>
<string name="screenrecord_device_audio_and_mic_label" msgid="1831323771978646841">"Zvok v napravi in mikrofon"</string>
<string name="screenrecord_start" msgid="330991441575775004">"Začni"</string>
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Nadaljuj"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Prekliči"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Deli"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Izbriši"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Snemanje zaslona je preklicano"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Videoposnetek zaslona je shranjen, dotaknite se za ogled"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Videoposnetek zaslona je izbrisan"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Napaka pri brisanju videoposnetka zaslona"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Dovoljenj ni bilo mogoče pridobiti"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Napaka pri začenjanju snemanja zaslona"</string>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index 1dbf9dea9dd8..60ef3a2561b2 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Vazhdo"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Anulo"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Ndaj"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Fshi"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Regjistrimi i ekranit u anulua"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Regjistrimi i ekranit u ruajt, trokit për ta parë"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Regjistrimi i ekranit u fshi"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Gabim gjatë fshirjes së regjistrimit të ekranit"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Marrja e lejeve dështoi"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Gabim gjatë nisjes së regjistrimit të ekranit"</string>
@@ -482,7 +480,7 @@
<string name="guest_wipe_session_title" msgid="7147965814683990944">"Mirë se erdhe, i ftuar!"</string>
<string name="guest_wipe_session_message" msgid="3393823610257065457">"Dëshiron ta vazhdosh sesionin tënd?"</string>
<string name="guest_wipe_session_wipe" msgid="8056836584445473309">"Fillo nga e para"</string>
- <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Po, vazhdo!"</string>
+ <string name="guest_wipe_session_dontwipe" msgid="3211052048269304205">"Po, vazhdo"</string>
<string name="guest_notification_title" msgid="4434456703930764167">"Përdorues vizitor"</string>
<string name="guest_notification_text" msgid="4202692942089571351">"Për të fshirë aplikacionet dhe të dhënat, hiqe përdoruesin vizitor"</string>
<string name="guest_notification_remove_action" msgid="4153019027696868099">"HIQ VIZITORIN"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index cfb33e89856f..083e45efc026 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Настави"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Откажи"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Дели"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Избриши"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Снимање екрана је отказано"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Снимак екрана је сачуван, додирните да бисте прегледали"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Снимак екрана је избрисан"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Дошло је до проблема при брисању снимка екрана"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Преузимање дозвола није успело"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Грешка при покретању снимања екрана"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index baa69b491a07..e2e6b7d31359 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Återuppta"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Avbryt"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Dela"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Radera"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Skärminspelningen har avbrutits"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Skärminspelningen har sparats, tryck här om du vill titta på den"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Skärminspelningen har raderats"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Det gick inte att radera skärminspelningen"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Behörighet saknas"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Det gick inte att starta skärminspelningen"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 09c42e771156..0abb58fdd15f 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Endelea"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Ghairi"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Shiriki"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Futa"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Imeghairi mchakato wa kurekodi skrini"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Imehifadhi rekodi ya skrini, gusa ili uangalie"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Imefuta rekodi ya skrini"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Hitilafu imetokea wakati wa kufuta rekodi ya skrini"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Imeshindwa kupata ruhusa"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Hitilafu imetokea wakati wa kuanza kurekodi skrini"</string>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 134fc2dcaa7d..f98e103ed9c4 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"மீண்டும் தொடங்கு"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"ரத்துசெய்"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"பகிர்"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"நீக்கு"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"திரை ரெக்கார்டிங் ரத்துசெய்யப்பட்டது"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"திரை ரெக்கார்டிங் சேமிக்கப்பட்டது, பார்க்கத் தட்டவும்"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"திரை ரெக்கார்டிங் நீக்கப்பட்டது"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"திரை ரெக்கார்டிங்கை நீக்குவதில் பிழை"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"அனுமதிகளைப் பெற இயலவில்லை"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"ஸ்கிரீன் ரெக்கார்டிங்கைத் தொடங்குவதில் பிழை"</string>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index a50399069ca3..73f969f485a6 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"కొనసాగించు"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"రద్దు చేయి"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"షేర్ చేయి"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"తొలగించు"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"స్క్రీన్ రికార్డ్ రద్దు చేయబడింది"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"స్క్రీన్ రికార్డింగ్ సేవ్ చేయబడింది, చూడటం కోసం నొక్కండి"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"స్క్రీన్ రికార్డింగ్ తొలగించబడింది"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"స్క్రీన్ రికార్డింగ్‌ని తొలగిస్తున్నప్పుడు ఎర్రర్ ఏర్పడింది"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"అనుమతులను పొందడం విఫలమైంది"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"స్క్రీన్ రికార్డింగ్ ప్రారంభించడంలో ఎర్రర్ ఏర్పడింది"</string>
@@ -695,7 +693,7 @@
<string name="notification_channel_unsilenced" msgid="94878840742161152">"ఈ నోటిఫికేషన్‌లు మిమ్మల్ని హెచ్చరిస్తాయి"</string>
<string name="inline_blocking_helper" msgid="2891486013649543452">"మీరు సాధారణంగా ఈ నోటిఫికేషన్‌లను విస్మరిస్తారు. \nవాటి ప్రదర్శనను కొనసాగించాలా?"</string>
<string name="inline_done_button" msgid="6043094985588909584">"పూర్తయింది"</string>
- <string name="inline_ok_button" msgid="603075490581280343">"అప్లై చేయి"</string>
+ <string name="inline_ok_button" msgid="603075490581280343">"అప్లయి చేయి"</string>
<string name="inline_keep_showing" msgid="8736001253507073497">"ఈ నోటిఫికేషన్‌లను చూపిస్తూ ఉండాలా?"</string>
<string name="inline_stop_button" msgid="2453460935438696090">"నోటిఫికేషన్‌లను ఆపివేయి"</string>
<string name="inline_deliver_silently_button" msgid="2714314213321223286">"నిశ్శబ్దంగా బట్వాడా చేయండి"</string>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 52d99171d654..1a9395a9b1fb 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -92,7 +92,7 @@
<string name="screenrecord_background_processing_label" msgid="7244617554884238898">"กำลังประมวลผลการอัดหน้าจอ"</string>
<string name="screenrecord_channel_description" msgid="4147077128486138351">"การแจ้งเตือนต่อเนื่องสำหรับเซสชันการบันทึกหน้าจอ"</string>
<string name="screenrecord_start_label" msgid="1750350278888217473">"เริ่มบันทึกเลยไหม"</string>
- <string name="screenrecord_description" msgid="1123231719680353736">"ขณะบันทึก ระบบ Android อาจบันทึกข้อมูลที่ละเอียดอ่อนที่ปรากฏบนหน้าจอหรือเล่นในอุปกรณ์ได้ ซึ่งรวมถึงรหัสผ่าน ข้อมูลการชำระเงิน รูปภาพ ข้อความ และเสียง"</string>
+ <string name="screenrecord_description" msgid="1123231719680353736">"ขณะบันทึก ระบบ Android อาจบันทึกข้อมูลที่ละเอียดอ่อนซึ่งปรากฏบนหน้าจอหรือเล่นในอุปกรณ์ได้ ซึ่งรวมถึงรหัสผ่าน ข้อมูลการชำระเงิน รูปภาพ ข้อความ และเสียง"</string>
<string name="screenrecord_audio_label" msgid="6183558856175159629">"บันทึกเสียง"</string>
<string name="screenrecord_device_audio_label" msgid="9016927171280567791">"เสียงจากอุปกรณ์"</string>
<string name="screenrecord_device_audio_description" msgid="4922694220572186193">"เสียงจากอุปกรณ์ เช่น เพลง การโทร และเสียงเรียกเข้า"</string>
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"ทำต่อ"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"ยกเลิก"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"แชร์"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"ลบ"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"ยกเลิกการบันทึกหน้าจอแล้ว"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"บันทึกการบันทึกหน้าจอแล้ว แตะเพื่อดู"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"ลบการบันทึกหน้าจอแล้ว"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"เกิดข้อผิดพลาดในการลบการบันทึกหน้าจอ"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"ขอสิทธิ์ไม่สำเร็จ"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"เกิดข้อผิดพลาดขณะเริ่มบันทึกหน้าจอ"</string>
@@ -339,7 +337,7 @@
<string name="accessibility_rotation_lock_on_landscape_changed" msgid="5785739044300729592">"ขณะนี้หน้าจอล็อกอยู่ในแนวนอน"</string>
<string name="accessibility_rotation_lock_on_portrait_changed" msgid="5580170829728987989">"ขณะนี้หน้าจอล็อกอยู่ในแนวตั้ง"</string>
<string name="dessert_case" msgid="9104973640704357717">"ชั้นแสดงของหวาน"</string>
- <string name="start_dreams" msgid="9131802557946276718">"โปรแกรมรักษาหน้าจอ"</string>
+ <string name="start_dreams" msgid="9131802557946276718">"โปรแกรมรักษาจอภาพ"</string>
<string name="ethernet_label" msgid="2203544727007463351">"อีเทอร์เน็ต"</string>
<string name="quick_settings_header_onboarding_text" msgid="1918085351115504765">"แตะไอคอนค้างไว้เพื่อดูตัวเลือกอื่นๆ"</string>
<string name="quick_settings_dnd_label" msgid="7728690179108024338">"ห้ามรบกวน"</string>
@@ -511,7 +509,7 @@
<string name="manage_notifications_text" msgid="6885645344647733116">"จัดการ"</string>
<string name="manage_notifications_history_text" msgid="57055985396576230">"ประวัติ"</string>
<string name="notification_section_header_incoming" msgid="850925217908095197">"ใหม่"</string>
- <string name="notification_section_header_gentle" msgid="6804099527336337197">"เงียบ"</string>
+ <string name="notification_section_header_gentle" msgid="6804099527336337197">"ปิดเสียง"</string>
<string name="notification_section_header_alerting" msgid="5581175033680477651">"การแจ้งเตือน"</string>
<string name="notification_section_header_conversations" msgid="821834744538345661">"การสนทนา"</string>
<string name="accessibility_notification_section_header_gentle_clear_all" msgid="6490207897764933919">"ล้างการแจ้งเตือนแบบไม่มีเสียงทั้งหมด"</string>
@@ -708,7 +706,7 @@
<string name="inline_silent_button_keep_alerting" msgid="6577845442184724992">"แจ้งเตือนต่อไป"</string>
<string name="inline_turn_off_notifications" msgid="8543989584403106071">"ปิดการแจ้งเตือน"</string>
<string name="inline_keep_showing_app" msgid="4393429060390649757">"แสดงการแจ้งเตือนจากแอปนี้ต่อไปไหม"</string>
- <string name="notification_silence_title" msgid="8608090968400832335">"เงียบ"</string>
+ <string name="notification_silence_title" msgid="8608090968400832335">"ปิดเสียง"</string>
<string name="notification_alert_title" msgid="3656229781017543655">"ค่าเริ่มต้น"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"บับเบิล"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"ไม่มีเสียงหรือการสั่น"</string>
@@ -856,7 +854,7 @@
<string name="left_icon" msgid="5036278531966897006">"ไอคอนทางซ้าย"</string>
<string name="right_icon" msgid="1103955040645237425">"ไอคอนทางขวา"</string>
<string name="drag_to_add_tiles" msgid="8933270127508303672">"กดค้างแล้วลากเพื่อเพิ่มการ์ด"</string>
- <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"กดการ์ดค้างไว้แล้วลากเพื่อจัดเรียงใหม่"</string>
+ <string name="drag_to_rearrange_tiles" msgid="2143204300089638620">"กดค้างแล้วลากเพื่อจัดเรียงการ์ดใหม่"</string>
<string name="drag_to_remove_tiles" msgid="4682194717573850385">"ลากมาที่นี่เพื่อนำออก"</string>
<string name="drag_to_remove_disabled" msgid="933046987838658850">"คุณต้องมีการ์ดอย่างน้อย <xliff:g id="MIN_NUM_TILES">%1$d</xliff:g> รายการ"</string>
<string name="qs_edit" msgid="5583565172803472437">"แก้ไข"</string>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index b7eca6399b7b..c37c1116de9e 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Ituloy"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Kanselahin"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Ibahagi"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"I-delete"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Kinansela ang pag-record ng screen"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Na-save ang pag-record ng screen, i-tap para tingnan"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Na-delete ang pag-record ng screen"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Error sa pag-delete sa pag-record ng screen"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Hindi nakuha ang mga pahintulot"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Nagkaroon ng error sa pagsisimula ng pag-record ng screen"</string>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index e5cd3f6b8204..108f00c41be6 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Devam ettir"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"İptal"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Paylaş"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Sil"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Ekran kaydı iptal edildi"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Ekran kaydı tamamlandı, görüntülemek için dokunun"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Ekran kaydı silindi"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Ekran kaydı silinirken hata oluştu"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"İzinler alınamadı"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Ekran kaydı başlatılırken hata oluştu"</string>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 412e5133fdac..90a512f3ecbe 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Відновити"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Скасувати"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Поділитися"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Видалити"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Запис екрана скасовано"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Запис екрана збережено. Натисніть, щоб переглянути"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Запис екрана видалено"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Не вдалося видалити запис екрана"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Не вдалось отримати дозволи"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Не вдалося почати запис екрана"</string>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index ab096baeebae..8a69b1cfb3dc 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"دوبارہ شروع کریں"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"منسوخ کریں"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"اشتراک کریں"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"حذف کریں"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"اسکرین ریکارڈنگ منسوخ ہو گئی"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"اسکرین ریکارڈنگ محفوظ ہو گئی، دیکھنے کیلئے تھپتھپائیں"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"اسکرین ریکارڈنگ حذف ہو گئی"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"اسکرین ریکارڈنگ کو حذف کرنے میں خرابی"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"اجازتیں حاصل کرنے میں ناکامی"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"اسکرین ریکارڈنگ شروع کرنے میں خرابی"</string>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index 123e9460a85b..47dd75c55b8d 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Davom etish"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Bekor qilish"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Ulashish"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"O‘chirish"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Ekrandan yozib olish bekor qilindi"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Ekrandan yozib olingan video saqlandi. Uni ochish uchun bildirishnomani bosing."</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Ekrandan yozib olingan video o‘chirib tashlandi"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Ekrandan yozib olingan vi olib tashlanmadi"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Zarur ruxsatlar olinmadi"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Ekranni yozib olish boshlanmadi"</string>
@@ -362,7 +360,7 @@
<string name="accessibility_quick_settings_rotation_value" msgid="2916484894750819251">"<xliff:g id="ID_1">%s</xliff:g> rejimi"</string>
<string name="quick_settings_rotation_locked_label" msgid="4420863550666310319">"Aylanmaydigan qilingan"</string>
<string name="quick_settings_rotation_locked_portrait_label" msgid="1194988975270484482">"Tik holat"</string>
- <string name="quick_settings_rotation_locked_landscape_label" msgid="2000295772687238645">"Eniga"</string>
+ <string name="quick_settings_rotation_locked_landscape_label" msgid="2000295772687238645">"Yotiq"</string>
<string name="quick_settings_ime_label" msgid="3351174938144332051">"Kiritish usuli"</string>
<string name="quick_settings_location_label" msgid="2621868789013389163">"Joylashuv"</string>
<string name="quick_settings_location_off_label" msgid="7923929131443915919">"Joylashuvni aniqlash xizmati yoqilmagan"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 41033e5fc6eb..344e292f1bd5 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Tiếp tục"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Hủy"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Chia sẻ"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Xóa"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Đã hủy bản ghi màn hình"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Đã lưu bản ghi màn hình, nhấn để xem"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Đã xóa bản ghi màn hình"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Lỗi khi xóa bản ghi màn hình"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Không được cấp đủ quyền"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Lỗi khi bắt đầu ghi màn hình"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 9b3c55ddf943..2a720d8f715f 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"继续"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"取消"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"分享"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"删除"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"已取消录制屏幕"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"屏幕录制内容已保存,点按即可查看"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"已删除屏幕录制内容"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"删除屏幕录制内容时出错"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"无法获取权限"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"启动屏幕录制时出错"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index e061aebcafdd..2d37a0ae1739 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"繼續"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"取消"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"分享"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"刪除"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"已取消錄影畫面"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"已儲存錄影畫面,輕按即可查看"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"已刪除錄影畫面"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"刪除錄影畫面時發生錯誤"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"無法獲得權限"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"開始錄影畫面時發生錯誤"</string>
@@ -716,7 +714,7 @@
<string name="notification_channel_summary_default" msgid="3282930979307248890">"可能會根據手機設定發出鈴聲或震動"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能會根據手機設定發出鈴聲或震動。「<xliff:g id="APP_NAME">%1$s</xliff:g>」的對話會預設以對話氣泡顯示。"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"為此內容建立浮動捷徑以保持注意力。"</string>
- <string name="notification_channel_summary_priority" msgid="7952654515769021553">"在對話部分的頂部以浮動對話氣泡顯示,並在上鎖畫面顯示個人檔案相片"</string>
+ <string name="notification_channel_summary_priority" msgid="7952654515769021553">"以浮動對話泡顯示在對話部分的頂部,並在上鎖畫面顯示個人檔案相片"</string>
<string name="notification_conversation_channel_settings" msgid="2409977688430606835">"設定"</string>
<string name="notification_priority_title" msgid="2079708866333537093">"重要"</string>
<string name="no_shortcut" msgid="8257177117568230126">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」不支援對話功能"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index a340e37fa2e1..14345873f2cf 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"繼續"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"取消"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"分享"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"刪除"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"已取消錄製螢幕畫面"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"已儲存螢幕畫面錄製內容,輕觸即可查看"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"已刪除螢幕畫面錄製內容"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"刪除螢幕畫面錄製內容時發生錯誤"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"無法取得權限"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"開始錄製螢幕畫面時發生錯誤"</string>
@@ -712,7 +710,7 @@
<string name="notification_alert_title" msgid="3656229781017543655">"預設"</string>
<string name="notification_bubble_title" msgid="8330481035191903164">"泡泡"</string>
<string name="notification_channel_summary_low" msgid="4860617986908931158">"不震動或發出聲音"</string>
- <string name="notification_conversation_summary_low" msgid="1734433426085468009">"不震動或發出聲音,並顯示在對話部分的下方"</string>
+ <string name="notification_conversation_summary_low" msgid="1734433426085468009">"不震動或發出聲音,並調整排序到其他對話下方"</string>
<string name="notification_channel_summary_default" msgid="3282930979307248890">"根據手機的設定響鈴或震動"</string>
<string name="notification_channel_summary_default_with_bubbles" msgid="1782419896613644568">"可能會根據手機的設定響鈴或震動。根據預設,來自「<xliff:g id="APP_NAME">%1$s</xliff:g>」的對話會以對話框形式顯示。"</string>
<string name="notification_channel_summary_bubble" msgid="7235935211580860537">"利用浮動式捷徑快速存取這項內容。"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 679659587d6e..7303e142f929 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -108,10 +108,8 @@
<string name="screenrecord_resume_label" msgid="4972223043729555575">"Qalisa kabusha"</string>
<string name="screenrecord_cancel_label" msgid="7850926573274483294">"Khansela"</string>
<string name="screenrecord_share_label" msgid="5025590804030086930">"Yabelana"</string>
- <string name="screenrecord_delete_label" msgid="1376347010553987058">"Susa"</string>
<string name="screenrecord_cancel_success" msgid="1775448688137393901">"Ukurekhoda isikrini kukhanseliwe"</string>
<string name="screenrecord_save_message" msgid="490522052388998226">"Ukurekhoda isikrini kulondoloziwe, thepha ukuze ubuke"</string>
- <string name="screenrecord_delete_description" msgid="1604522770162810570">"Ukurekhoda isikrini kususiwe"</string>
<string name="screenrecord_delete_error" msgid="2870506119743013588">"Iphutha lokususa ukurekhoda isikrini"</string>
<string name="screenrecord_permission_error" msgid="7856841237023137686">"Yehlulekile ukuthola izimvume"</string>
<string name="screenrecord_start_error" msgid="2200660692479682368">"Iphutha lokuqala ukurekhoda isikrini"</string>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 0d40a9fa26d4..5b7bee653154 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1350,15 +1350,19 @@
<dimen name="controls_management_side_padding">16dp</dimen>
<dimen name="controls_management_titles_margin">16dp</dimen>
<dimen name="controls_management_footer_side_margin">8dp</dimen>
+ <dimen name="controls_management_footer_top_margin">@dimen/controls_management_footer_side_margin</dimen>
<dimen name="controls_management_list_margin">16dp</dimen>
+ <dimen name="controls_management_indicator_top_margin">@dimen/controls_management_list_margin</dimen>
<dimen name="controls_management_apps_list_margin">64dp</dimen>
<dimen name="controls_management_editing_list_margin">48dp</dimen>
<dimen name="controls_management_editing_divider_margin">24dp</dimen>
<dimen name="controls_management_apps_extra_side_margin">8dp</dimen>
<dimen name="controls_management_zone_top_margin">32dp</dimen>
+ <dimen name="controls_management_favorites_top_margin">@dimen/controls_management_zone_top_margin</dimen>
<dimen name="controls_management_status_side_margin">16dp</dimen>
<dimen name="controls_management_page_indicator_height">24dp</dimen>
<dimen name="controls_management_checkbox_size">25dp</dimen>
+ <dimen name="controls_management_footer_height">72dp</dimen>
<dimen name="controls_title_size">24sp</dimen>
<dimen name="controls_subtitle_size">16sp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
index 5f8815665d88..2deeb1230f09 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
@@ -39,15 +39,21 @@ import javax.inject.Singleton;
*/
@Singleton
public class ForegroundServiceController {
- public static final int[] APP_OPS = new int[] {AppOpsManager.OP_SYSTEM_ALERT_WINDOW};
+ public static final int[] APP_OPS = new int[] {AppOpsManager.OP_CAMERA,
+ AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+ AppOpsManager.OP_RECORD_AUDIO,
+ AppOpsManager.OP_COARSE_LOCATION,
+ AppOpsManager.OP_FINE_LOCATION};
private final SparseArray<ForegroundServicesUserState> mUserServices = new SparseArray<>();
private final Object mMutex = new Object();
+ private final NotificationEntryManager mEntryManager;
private final Handler mMainHandler;
@Inject
- public ForegroundServiceController(AppOpsController appOpsController,
- @Main Handler mainHandler) {
+ public ForegroundServiceController(NotificationEntryManager entryManager,
+ AppOpsController appOpsController, @Main Handler mainHandler) {
+ mEntryManager = entryManager;
mMainHandler = mainHandler;
appOpsController.addCallback(APP_OPS, (code, uid, packageName, active) -> {
mMainHandler.post(() -> {
@@ -81,6 +87,19 @@ public class ForegroundServiceController {
}
/**
+ * Returns the keys for notifications from this package using the standard template,
+ * if they exist.
+ */
+ @Nullable
+ public ArraySet<String> getStandardLayoutKeys(int userId, String pkg) {
+ synchronized (mMutex) {
+ final ForegroundServicesUserState services = mUserServices.get(userId);
+ if (services == null) return null;
+ return services.getStandardLayoutKeys(pkg);
+ }
+ }
+
+ /**
* Gets active app ops for this user and package
*/
@Nullable
@@ -121,6 +140,31 @@ public class ForegroundServiceController {
userServices.removeOp(packageName, appOpCode);
}
}
+
+ // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
+ // AppOpsCoordinator
+ // Update appOps if there are associated pending or visible notifications
+ final Set<String> notificationKeys = getStandardLayoutKeys(userId, packageName);
+ if (notificationKeys != null) {
+ boolean changed = false;
+ for (String key : notificationKeys) {
+ final NotificationEntry entry = mEntryManager.getPendingOrActiveNotif(key);
+ if (entry != null
+ && uid == entry.getSbn().getUid()
+ && packageName.equals(entry.getSbn().getPackageName())) {
+ synchronized (entry.mActiveAppOps) {
+ if (active) {
+ changed |= entry.mActiveAppOps.add(appOpCode);
+ } else {
+ changed |= entry.mActiveAppOps.remove(appOpCode);
+ }
+ }
+ }
+ }
+ if (changed) {
+ mEntryManager.updateNotifications("appOpChanged pkg=" + packageName);
+ }
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
index 1515272569d6..bb445832da93 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceNotificationListener.java
@@ -172,8 +172,24 @@ public class ForegroundServiceNotificationListener {
sbn.getPackageName(), sbn.getKey());
}
}
+ tagAppOps(entry);
return true;
},
true /* create if not found */);
}
+
+ // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
+ // AppOpsCoordinator
+ private void tagAppOps(NotificationEntry entry) {
+ final StatusBarNotification sbn = entry.getSbn();
+ ArraySet<Integer> activeOps = mForegroundServiceController.getAppOps(
+ sbn.getUserId(),
+ sbn.getPackageName());
+ synchronized (entry.mActiveAppOps) {
+ entry.mActiveAppOps.clear();
+ if (activeOps != null) {
+ entry.mActiveAppOps.addAll(activeOps);
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 1e556a3ed402..58d5776543a9 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -301,7 +301,7 @@ public class BubbleExpandedView extends LinearLayout {
mActivityView = new ActivityView(mContext, null /* attrs */, 0 /* defStyle */,
true /* singleTaskInstance */, false /* usePublicVirtualDisplay*/,
- true /* disableSurfaceViewBackgroundLayer */);
+ true /* disableSurfaceViewBackgroundLayer */, true /* useTrustedDisplay */);
// Set ActivityView's alpha value as zero, since there is no view content to be shown.
setContentVisibility(false);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java
index c1dd8c36ff6f..48a9b91721f5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleLoggerImpl.java
@@ -30,10 +30,6 @@ public class BubbleLoggerImpl extends UiEventLoggerImpl implements BubbleLogger
* @param e UI event
*/
public void log(Bubble b, UiEventEnum e) {
- if (b.getInstanceId() == null) {
- // Added from persistence -- TODO log this with specific event?
- return;
- }
logWithInstanceId(e, b.getAppUid(), b.getPackageName(), b.getInstanceId());
}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
index 1bda841d4a63..d930c98cabe1 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
@@ -87,6 +87,10 @@ class ControlsFavoritePersistenceWrapper(
* @param list a list of favorite controls. The list will be stored in the same order.
*/
fun storeFavorites(structures: List<StructureInfo>) {
+ if (structures.isEmpty() && !file.exists()) {
+ // Do not create a new file to store nothing
+ return
+ }
executor.execute {
Log.d(TAG, "Saving data to file: $file")
val atomicFile = AtomicFile(file)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
index 31830b94e8e4..40662536e57e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlAdapter.kt
@@ -263,6 +263,7 @@ internal class ControlHolder(
val context = itemView.context
val fg = context.getResources().getColorStateList(ri.foreground, context.getTheme())
+ icon.imageTintList = null
ci.customIcon?.let {
icon.setImageIcon(it)
} ?: run {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 5f75c96be128..5a525974f3cb 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -104,6 +104,7 @@ class ControlsUiControllerImpl @Inject constructor (
private var hidden = true
private lateinit var dismissGlobalActions: Runnable
private val popupThemedContext = ContextThemeWrapper(context, R.style.Control_ListPopupWindow)
+ private var retainCache = false
private val collator = Collator.getInstance(context.resources.configuration.locales[0])
private val localeComparator = compareBy<SelectionItem, CharSequence>(collator) {
@@ -149,6 +150,7 @@ class ControlsUiControllerImpl @Inject constructor (
this.parent = parent
this.dismissGlobalActions = dismissGlobalActions
hidden = false
+ retainCache = false
allStructures = controlsController.get().getFavorites()
selectedStructure = loadPreference(allStructures)
@@ -235,6 +237,8 @@ class ControlsUiControllerImpl @Inject constructor (
}
putIntentExtras(i, si)
startActivity(context, i)
+
+ retainCache = true
}
private fun putIntentExtras(intent: Intent, si: StructureInfo) {
@@ -497,7 +501,7 @@ class ControlsUiControllerImpl @Inject constructor (
controlsListingController.get().removeCallback(listingCallback)
- RenderInfo.clearCache()
+ if (!retainCache) RenderInfo.clearCache()
}
override fun onRefreshState(componentName: ComponentName, controls: List<Control>) {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
index 1e99a7b733e2..e2361d8f415a 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemServicesModule.java
@@ -42,6 +42,7 @@ import android.hardware.SensorPrivacyManager;
import android.hardware.display.DisplayManager;
import android.media.AudioManager;
import android.media.MediaRouter2Manager;
+import android.media.session.MediaSessionManager;
import android.net.ConnectivityManager;
import android.net.NetworkScoreManager;
import android.net.wifi.WifiManager;
@@ -219,6 +220,11 @@ public class SystemServicesModule {
}
@Provides
+ static MediaSessionManager provideMediaSessionManager(Context context) {
+ return context.getSystemService(MediaSessionManager.class);
+ }
+
+ @Provides
@Singleton
static NetworkScoreManager provideNetworkScoreManager(Context context) {
return context.getSystemService(NetworkScoreManager.class);
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index ae7d82ac4a5e..253a35c55698 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -430,8 +430,12 @@ public class DozeMachine {
/** Give the Part a chance to clean itself up. */
default void destroy() {}
- /** Alerts that the screenstate is being changed. */
- default void onScreenState(int state) {}
+ /**
+ * Alerts that the screenstate is being changed.
+ * Note: This may be called from within a call to transitionTo, so local DozeState may not
+ * be accurate nor match with the new displayState.
+ */
+ default void onScreenState(int displayState) {}
}
/** A wrapper interface for {@link android.service.dreams.DreamService} */
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 64cfb4bcd058..a11997b6b845 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -69,7 +69,6 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
* --ei brightness_bucket 1}
*/
private int mDebugBrightnessBucket = -1;
- private DozeMachine.State mState;
@VisibleForTesting
public DozeScreenBrightness(Context context, DozeMachine.Service service,
@@ -109,7 +108,6 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
@Override
public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
- mState = newState;
switch (newState) {
case INITIALIZED:
case DOZE:
@@ -127,10 +125,7 @@ public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachi
@Override
public void onScreenState(int state) {
- if (!mScreenOff
- && (mState == DozeMachine.State.DOZE_AOD
- || mState == DozeMachine.State.DOZE_AOD_DOCKED)
- && (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND)) {
+ if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) {
setLightSensorEnabled(true);
} else {
setLightSensorEnabled(false);
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 0554dc80cba5..ff25439a5f9f 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -19,6 +19,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.ScreenshotSource.SCREENSHOT_GLOBAL_ACTIONS;
import static android.view.WindowManager.TAKE_SCREENSHOT_FULLSCREEN;
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
@@ -548,7 +549,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
if (!mDeviceProvisioned && !action.showBeforeProvisioning()) {
return false;
}
- return true;
+ return action.shouldShow();
}
/**
@@ -961,6 +962,8 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
@VisibleForTesting
class ScreenshotAction extends SinglePressAction implements LongPressAction {
+ final String KEY_SYSTEM_NAV_2BUTTONS = "system_nav_2buttons";
+
public ScreenshotAction() {
super(R.drawable.ic_screenshot, R.string.global_action_screenshot);
}
@@ -993,6 +996,19 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
}
@Override
+ public boolean shouldShow() {
+ // Include screenshot in power menu for legacy nav because it is not accessible
+ // through Recents in that mode
+ return is2ButtonNavigationEnabled();
+ }
+
+ boolean is2ButtonNavigationEnabled() {
+ return NAV_BAR_MODE_2BUTTON == mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_navBarInteractionMode);
+ }
+
+
+ @Override
public boolean onLongPress() {
if (FeatureFlagUtils.isEnabled(mContext, FeatureFlagUtils.SCREENRECORD_LONG_PRESS)) {
mUiEventLogger.log(GlobalActionsEvent.GA_SCREENSHOT_LONG_PRESS);
@@ -1615,6 +1631,10 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
* @return
*/
CharSequence getMessage();
+
+ default boolean shouldShow() {
+ return true;
+ }
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 15c60921cca5..1808035df027 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -11,6 +11,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
+import androidx.annotation.VisibleForTesting
import com.android.systemui.R
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.plugins.ActivityStarter
@@ -22,6 +23,7 @@ import com.android.systemui.util.Utils
import com.android.systemui.util.animation.UniqueObjectHostView
import com.android.systemui.util.animation.requiresRemeasuring
import com.android.systemui.util.concurrency.DelayableExecutor
+import java.util.TreeMap
import javax.inject.Inject
import javax.inject.Provider
import javax.inject.Singleton
@@ -41,7 +43,7 @@ class MediaCarouselController @Inject constructor(
private val mediaHostStatesManager: MediaHostStatesManager,
private val activityStarter: ActivityStarter,
@Main executor: DelayableExecutor,
- mediaManager: MediaDataFilter,
+ private val mediaManager: MediaDataManager,
configurationController: ConfigurationController,
falsingManager: FalsingManager
) {
@@ -103,13 +105,12 @@ class MediaCarouselController @Inject constructor(
private val mediaCarousel: MediaScrollView
private val mediaCarouselScrollHandler: MediaCarouselScrollHandler
val mediaFrame: ViewGroup
- val mediaPlayers: MutableMap<String, MediaControlPanel> = mutableMapOf()
private lateinit var settingsButton: View
- private val mediaData: MutableMap<String, MediaData> = mutableMapOf()
private val mediaContent: ViewGroup
private val pageIndicator: PageIndicator
private val visualStabilityCallback: VisualStabilityManager.Callback
private var needsReordering: Boolean = false
+ private var keysNeedRemoval = mutableSetOf<String>()
private var isRtl: Boolean = false
set(value) {
if (value != field) {
@@ -123,7 +124,7 @@ class MediaCarouselController @Inject constructor(
set(value) {
if (field != value) {
field = value
- for (player in mediaPlayers.values) {
+ for (player in MediaPlayerData.players()) {
player.setListening(field)
}
}
@@ -161,6 +162,10 @@ class MediaCarouselController @Inject constructor(
needsReordering = false
reorderAllPlayers()
}
+
+ keysNeedRemoval.forEach { removePlayer(it) }
+ keysNeedRemoval.clear()
+
// Let's reset our scroll position
mediaCarouselScrollHandler.scrollToStart()
}
@@ -168,20 +173,23 @@ class MediaCarouselController @Inject constructor(
true /* persistent */)
mediaManager.addListener(object : MediaDataManager.Listener {
override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {
- oldKey?.let { mediaData.remove(it) }
- if (!data.active && !Utils.useMediaResumption(context)) {
- // This view is inactive, let's remove this! This happens e.g when dismissing /
- // timing out a view. We still have the data around because resumption could
- // be on, but we should save the resources and release this.
- onMediaDataRemoved(key)
+ addOrUpdatePlayer(key, oldKey, data)
+ val canRemove = data.isPlaying?.let { !it } ?: data.isClearable
+ if (canRemove && !Utils.useMediaResumption(context)) {
+ // This view isn't playing, let's remove this! This happens e.g when
+ // dismissing/timing out a view. We still have the data around because
+ // resumption could be on, but we should save the resources and release this.
+ if (visualStabilityManager.isReorderingAllowed) {
+ onMediaDataRemoved(key)
+ } else {
+ keysNeedRemoval.add(key)
+ }
} else {
- mediaData.put(key, data)
- addOrUpdatePlayer(key, oldKey, data)
+ keysNeedRemoval.remove(key)
}
}
override fun onMediaDataRemoved(key: String) {
- mediaData.remove(key)
removePlayer(key)
}
})
@@ -224,53 +232,36 @@ class MediaCarouselController @Inject constructor(
}
private fun reorderAllPlayers() {
- for (mediaPlayer in mediaPlayers.values) {
- val view = mediaPlayer.view?.player
- if (mediaPlayer.isPlaying && mediaContent.indexOfChild(view) != 0) {
- mediaContent.removeView(view)
- mediaContent.addView(view, 0)
+ mediaContent.removeAllViews()
+ for (mediaPlayer in MediaPlayerData.players()) {
+ mediaPlayer.view?.let {
+ mediaContent.addView(it.player)
}
}
mediaCarouselScrollHandler.onPlayersChanged()
}
private fun addOrUpdatePlayer(key: String, oldKey: String?, data: MediaData) {
- // If the key was changed, update entry
- val oldData = mediaPlayers[oldKey]
- if (oldData != null) {
- val oldData = mediaPlayers.remove(oldKey)
- mediaPlayers.put(key, oldData!!)?.let {
- Log.wtf(TAG, "new key $key already exists when migrating from $oldKey")
- }
- }
- var existingPlayer = mediaPlayers[key]
+ val existingPlayer = MediaPlayerData.getMediaPlayer(key, oldKey)
if (existingPlayer == null) {
- existingPlayer = mediaControlPanelFactory.get()
- existingPlayer.attach(PlayerViewHolder.create(LayoutInflater.from(context),
- mediaContent))
- existingPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
- mediaPlayers[key] = existingPlayer
+ var newPlayer = mediaControlPanelFactory.get()
+ newPlayer.attach(PlayerViewHolder.create(LayoutInflater.from(context), mediaContent))
+ newPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)
- existingPlayer.view?.player?.setLayoutParams(lp)
- existingPlayer.bind(data)
- existingPlayer.setListening(currentlyExpanded)
- updatePlayerToState(existingPlayer, noAnimation = true)
- if (existingPlayer.isPlaying) {
- mediaContent.addView(existingPlayer.view?.player, 0)
- } else {
- mediaContent.addView(existingPlayer.view?.player)
- }
+ newPlayer.view?.player?.setLayoutParams(lp)
+ newPlayer.bind(data)
+ newPlayer.setListening(currentlyExpanded)
+ MediaPlayerData.addMediaPlayer(key, data, newPlayer)
+ updatePlayerToState(newPlayer, noAnimation = true)
+ reorderAllPlayers()
} else {
existingPlayer.bind(data)
- if (existingPlayer.isPlaying &&
- mediaContent.indexOfChild(existingPlayer.view?.player) != 0) {
- if (visualStabilityManager.isReorderingAllowed) {
- mediaContent.removeView(existingPlayer.view?.player)
- mediaContent.addView(existingPlayer.view?.player, 0)
- } else {
- needsReordering = true
- }
+ MediaPlayerData.addMediaPlayer(key, data, existingPlayer)
+ if (visualStabilityManager.isReorderingAllowed) {
+ reorderAllPlayers()
+ } else {
+ needsReordering = true
}
}
updatePageIndicator()
@@ -278,29 +269,27 @@ class MediaCarouselController @Inject constructor(
mediaCarousel.requiresRemeasuring = true
// Check postcondition: mediaContent should have the same number of children as there are
// elements in mediaPlayers.
- if (mediaPlayers.size != mediaContent.childCount) {
+ if (MediaPlayerData.players().size != mediaContent.childCount) {
Log.wtf(TAG, "Size of players list and number of views in carousel are out of sync")
}
}
private fun removePlayer(key: String) {
- val removed = mediaPlayers.remove(key)
+ val removed = MediaPlayerData.removeMediaPlayer(key)
removed?.apply {
mediaCarouselScrollHandler.onPrePlayerRemoved(removed)
mediaContent.removeView(removed.view?.player)
removed.onDestroy()
mediaCarouselScrollHandler.onPlayersChanged()
updatePageIndicator()
+
+ // Inform the media manager of a potentially late dismissal
+ mediaManager.dismissMediaData(key, 0L)
}
}
private fun recreatePlayers() {
- // Note that this will scramble the order of players. Actively playing sessions will, at
- // least, still be put in the front. If we want to maintain order, then more work is
- // needed.
- mediaData.forEach {
- key, data ->
- removePlayer(key)
+ MediaPlayerData.mediaData().forEach { (key, data) ->
addOrUpdatePlayer(key = key, oldKey = null, data = data)
}
}
@@ -338,7 +327,7 @@ class MediaCarouselController @Inject constructor(
currentStartLocation = startLocation
currentEndLocation = endLocation
currentTransitionProgress = progress
- for (mediaPlayer in mediaPlayers.values) {
+ for (mediaPlayer in MediaPlayerData.players()) {
updatePlayerToState(mediaPlayer, immediately)
}
maybeResetSettingsCog()
@@ -387,7 +376,7 @@ class MediaCarouselController @Inject constructor(
private fun updateCarouselDimensions() {
var width = 0
var height = 0
- for (mediaPlayer in mediaPlayers.values) {
+ for (mediaPlayer in MediaPlayerData.players()) {
val controller = mediaPlayer.mediaViewController
// When transitioning the view to gone, the view gets smaller, but the translation
// Doesn't, let's add the translation
@@ -449,7 +438,7 @@ class MediaCarouselController @Inject constructor(
this.desiredLocation = desiredLocation
this.desiredHostState = it
currentlyExpanded = it.expansion > 0
- for (mediaPlayer in mediaPlayers.values) {
+ for (mediaPlayer in MediaPlayerData.players()) {
if (animate) {
mediaPlayer.mediaViewController.animatePendingStateChange(
duration = duration,
@@ -471,7 +460,7 @@ class MediaCarouselController @Inject constructor(
}
fun closeGuts() {
- mediaPlayers.values.forEach {
+ MediaPlayerData.players().forEach {
it.closeGuts(true)
}
}
@@ -498,3 +487,49 @@ class MediaCarouselController @Inject constructor(
}
}
}
+
+@VisibleForTesting
+internal object MediaPlayerData {
+ private data class MediaSortKey(
+ val data: MediaData,
+ val updateTime: Long = 0
+ )
+
+ private val comparator =
+ compareByDescending<MediaSortKey> { it.data.isPlaying }
+ .thenByDescending { it.data.isLocalSession }
+ .thenByDescending { !it.data.resumption }
+ .thenByDescending { it.updateTime }
+
+ private val mediaPlayers = TreeMap<MediaSortKey, MediaControlPanel>(comparator)
+ private val mediaData: MutableMap<String, MediaSortKey> = mutableMapOf()
+
+ fun addMediaPlayer(key: String, data: MediaData, player: MediaControlPanel) {
+ removeMediaPlayer(key)
+ val sortKey = MediaSortKey(data, System.currentTimeMillis())
+ mediaData.put(key, sortKey)
+ mediaPlayers.put(sortKey, player)
+ }
+
+ fun getMediaPlayer(key: String, oldKey: String?): MediaControlPanel? {
+ // If the key was changed, update entry
+ oldKey?.let {
+ if (it != key) {
+ mediaData.remove(it)?.let { sortKey -> mediaData.put(key, sortKey) }
+ }
+ }
+ return mediaData.get(key)?.let { mediaPlayers.get(it) }
+ }
+
+ fun removeMediaPlayer(key: String) = mediaData.remove(key)?.let { mediaPlayers.remove(it) }
+
+ fun mediaData() = mediaData.entries.map { e -> Pair(e.key, e.value.data) }
+
+ fun players() = mediaPlayers.values
+
+ @VisibleForTesting
+ fun clear() {
+ mediaData.clear()
+ mediaPlayers.clear()
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
index dafc52ad8025..40a879abde34 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaData.kt
@@ -82,6 +82,10 @@ data class MediaData(
*/
var resumeAction: Runnable?,
/**
+ * Local or remote playback
+ */
+ var isLocalSession: Boolean = true,
+ /**
* Indicates that this player is a resumption player (ie. It only shows a play actions which
* will start the app and start playing).
*/
@@ -90,7 +94,17 @@ data class MediaData(
* Notification key for cancelling a media player after a timeout (when not using resumption.)
*/
val notificationKey: String? = null,
- var hasCheckedForResume: Boolean = false
+ var hasCheckedForResume: Boolean = false,
+
+ /**
+ * If apps do not report PlaybackState, set as null to imply 'undetermined'
+ */
+ val isPlaying: Boolean? = null,
+
+ /**
+ * Set from the notification and used as fallback when PlaybackState cannot be determined
+ */
+ val isClearable: Boolean = true
)
/** State of a media action. */
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt
index d0642ccf9714..aa3699e9a22b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt
@@ -17,65 +17,48 @@
package com.android.systemui.media
import javax.inject.Inject
-import javax.inject.Singleton
/**
- * Combines updates from [MediaDataManager] with [MediaDeviceManager].
+ * Combines [MediaDataManager.Listener] events with [MediaDeviceManager.Listener] events.
*/
-@Singleton
-class MediaDataCombineLatest @Inject constructor(
- private val dataSource: MediaDataManager,
- private val deviceSource: MediaDeviceManager
-) {
+class MediaDataCombineLatest @Inject constructor() : MediaDataManager.Listener,
+ MediaDeviceManager.Listener {
+
private val listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
private val entries: MutableMap<String, Pair<MediaData?, MediaDeviceData?>> = mutableMapOf()
- init {
- dataSource.addListener(object : MediaDataManager.Listener {
- override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {
- if (oldKey != null && oldKey != key && entries.contains(oldKey)) {
- entries[key] = data to entries.remove(oldKey)?.second
- update(key, oldKey)
- } else {
- entries[key] = data to entries[key]?.second
- update(key, key)
- }
- }
- override fun onMediaDataRemoved(key: String) {
- remove(key)
- }
- })
- deviceSource.addListener(object : MediaDeviceManager.Listener {
- override fun onMediaDeviceChanged(
- key: String,
- oldKey: String?,
- data: MediaDeviceData?
- ) {
- if (oldKey != null && oldKey != key && entries.contains(oldKey)) {
- entries[key] = entries.remove(oldKey)?.first to data
- update(key, oldKey)
- } else {
- entries[key] = entries[key]?.first to data
- update(key, key)
- }
- }
- override fun onKeyRemoved(key: String) {
- remove(key)
- }
- })
+ override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {
+ if (oldKey != null && oldKey != key && entries.contains(oldKey)) {
+ entries[key] = data to entries.remove(oldKey)?.second
+ update(key, oldKey)
+ } else {
+ entries[key] = data to entries[key]?.second
+ update(key, key)
+ }
}
- /**
- * Get a map of all non-null data entries
- */
- fun getData(): Map<String, MediaData> {
- return entries.filter {
- (key, pair) -> pair.first != null && pair.second != null
- }.mapValues {
- (key, pair) -> pair.first!!.copy(device = pair.second)
+ override fun onMediaDataRemoved(key: String) {
+ remove(key)
+ }
+
+ override fun onMediaDeviceChanged(
+ key: String,
+ oldKey: String?,
+ data: MediaDeviceData?
+ ) {
+ if (oldKey != null && oldKey != key && entries.contains(oldKey)) {
+ entries[key] = entries.remove(oldKey)?.first to data
+ update(key, oldKey)
+ } else {
+ entries[key] = entries[key]?.first to data
+ update(key, key)
}
}
+ override fun onKeyRemoved(key: String) {
+ remove(key)
+ }
+
/**
* Add a listener for [MediaData] changes that has been combined with latest [MediaDeviceData].
*/
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
index 662831e4a445..1f580a953d09 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt
@@ -24,32 +24,32 @@ import com.android.systemui.settings.CurrentUserTracker
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import java.util.concurrent.Executor
import javax.inject.Inject
-import javax.inject.Singleton
private const val TAG = "MediaDataFilter"
+private const val DEBUG = true
/**
* Filters data updates from [MediaDataCombineLatest] based on the current user ID, and handles user
* switches (removing entries for the previous user, adding back entries for the current user)
*
- * This is added downstream of [MediaDataManager] since we may still need to handle callbacks from
- * background users (e.g. timeouts) that UI classes should ignore.
- * Instead, UI classes should listen to this so they can stay in sync with the current user.
+ * This is added at the end of the pipeline since we may still need to handle callbacks from
+ * background users (e.g. timeouts).
*/
-@Singleton
class MediaDataFilter @Inject constructor(
- private val dataSource: MediaDataCombineLatest,
private val broadcastDispatcher: BroadcastDispatcher,
private val mediaResumeListener: MediaResumeListener,
- private val mediaDataManager: MediaDataManager,
private val lockscreenUserManager: NotificationLockscreenUserManager,
@Main private val executor: Executor
) : MediaDataManager.Listener {
private val userTracker: CurrentUserTracker
- private val listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
+ private val _listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
+ internal val listeners: Set<MediaDataManager.Listener>
+ get() = _listeners.toSet()
+ internal lateinit var mediaDataManager: MediaDataManager
- // The filtered mediaEntries, which will be a subset of all mediaEntries in MediaDataManager
- private val mediaEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()
+ private val allEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()
+ // The filtered userEntries, which will be a subset of all userEntries in MediaDataManager
+ private val userEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()
init {
userTracker = object : CurrentUserTracker(broadcastDispatcher) {
@@ -59,31 +59,34 @@ class MediaDataFilter @Inject constructor(
}
}
userTracker.startTracking()
- dataSource.addListener(this)
}
override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {
+ if (oldKey != null && oldKey != key) {
+ allEntries.remove(oldKey)
+ }
+ allEntries.put(key, data)
+
if (!lockscreenUserManager.isCurrentProfile(data.userId)) {
return
}
- if (oldKey != null) {
- mediaEntries.remove(oldKey)
+ if (oldKey != null && oldKey != key) {
+ userEntries.remove(oldKey)
}
- mediaEntries.put(key, data)
+ userEntries.put(key, data)
// Notify listeners
- val listenersCopy = listeners.toSet()
- listenersCopy.forEach {
+ listeners.forEach {
it.onMediaDataLoaded(key, oldKey, data)
}
}
override fun onMediaDataRemoved(key: String) {
- mediaEntries.remove(key)?.let {
+ allEntries.remove(key)
+ userEntries.remove(key)?.let {
// Only notify listeners if something actually changed
- val listenersCopy = listeners.toSet()
- listenersCopy.forEach {
+ listeners.forEach {
it.onMediaDataRemoved(key)
}
}
@@ -92,22 +95,22 @@ class MediaDataFilter @Inject constructor(
@VisibleForTesting
internal fun handleUserSwitched(id: Int) {
// If the user changes, remove all current MediaData objects and inform listeners
- val listenersCopy = listeners.toSet()
- val keyCopy = mediaEntries.keys.toMutableList()
+ val listenersCopy = listeners
+ val keyCopy = userEntries.keys.toMutableList()
// Clear the list first, to make sure callbacks from listeners if we have any entries
// are up to date
- mediaEntries.clear()
+ userEntries.clear()
keyCopy.forEach {
- Log.d(TAG, "Removing $it after user change")
+ if (DEBUG) Log.d(TAG, "Removing $it after user change")
listenersCopy.forEach { listener ->
listener.onMediaDataRemoved(it)
}
}
- dataSource.getData().forEach { (key, data) ->
+ allEntries.forEach { (key, data) ->
if (lockscreenUserManager.isCurrentProfile(data.userId)) {
- Log.d(TAG, "Re-adding $key after user change")
- mediaEntries.put(key, data)
+ if (DEBUG) Log.d(TAG, "Re-adding $key after user change")
+ userEntries.put(key, data)
listenersCopy.forEach { listener ->
listener.onMediaDataLoaded(key, null, data)
}
@@ -119,7 +122,8 @@ class MediaDataFilter @Inject constructor(
* Invoked when the user has dismissed the media carousel
*/
fun onSwipeToDismiss() {
- val mediaKeys = mediaEntries.keys.toSet()
+ if (DEBUG) Log.d(TAG, "Media carousel swiped away")
+ val mediaKeys = userEntries.keys.toSet()
mediaKeys.forEach {
mediaDataManager.setTimedOut(it, timedOut = true)
}
@@ -128,26 +132,20 @@ class MediaDataFilter @Inject constructor(
/**
* Are there any media notifications active?
*/
- fun hasActiveMedia() = mediaEntries.any { it.value.active }
+ fun hasActiveMedia() = userEntries.any { it.value.active }
/**
* Are there any media entries we should display?
- * If resumption is enabled, this will include inactive players
- * If resumption is disabled, we only want to show active players
*/
- fun hasAnyMedia() = if (mediaResumeListener.isResumptionEnabled()) {
- mediaEntries.isNotEmpty()
- } else {
- hasActiveMedia()
- }
+ fun hasAnyMedia() = userEntries.isNotEmpty()
/**
* Add a listener for filtered [MediaData] changes
*/
- fun addListener(listener: MediaDataManager.Listener) = listeners.add(listener)
+ fun addListener(listener: MediaDataManager.Listener) = _listeners.add(listener)
/**
* Remove a listener that was registered with addListener
*/
- fun removeListener(listener: MediaDataManager.Listener) = listeners.remove(listener)
-} \ No newline at end of file
+ fun removeListener(listener: MediaDataManager.Listener) = _listeners.remove(listener)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
index 33475aca0bfb..bb11efeebf08 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt
@@ -31,6 +31,7 @@ import android.graphics.drawable.Drawable
import android.graphics.drawable.Icon
import android.media.MediaDescription
import android.media.MediaMetadata
+import android.media.session.MediaController
import android.media.session.MediaSession
import android.net.Uri
import android.os.UserHandle
@@ -44,6 +45,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.NotificationMediaManager.isPlayingState
import com.android.systemui.statusbar.notification.MediaNotificationProcessor
import com.android.systemui.statusbar.notification.row.HybridGroupManager
import com.android.systemui.util.Assert
@@ -55,8 +57,6 @@ import java.io.PrintWriter
import java.util.concurrent.Executor
import javax.inject.Inject
import javax.inject.Singleton
-import kotlin.collections.ArrayList
-import kotlin.collections.LinkedHashMap
// URI fields to try loading album art from
private val ART_URIS = arrayOf(
@@ -66,6 +66,7 @@ private val ART_URIS = arrayOf(
)
private const val TAG = "MediaDataManager"
+private const val DEBUG = true
private const val DEFAULT_LUMINOSITY = 0.25f
private const val LUMINOSITY_THRESHOLD = 0.05f
private const val SATURATION_MULTIPLIER = 0.8f
@@ -98,23 +99,23 @@ class MediaDataManager(
dumpManager: DumpManager,
mediaTimeoutListener: MediaTimeoutListener,
mediaResumeListener: MediaResumeListener,
+ mediaSessionBasedFilter: MediaSessionBasedFilter,
+ mediaDeviceManager: MediaDeviceManager,
+ mediaDataCombineLatest: MediaDataCombineLatest,
+ private val mediaDataFilter: MediaDataFilter,
private var useMediaResumption: Boolean,
private val useQsMediaPlayer: Boolean
) : Dumpable {
- private val listeners: MutableSet<Listener> = mutableSetOf()
+ // Internal listeners are part of the internal pipeline. External listeners (those registered
+ // with [MediaDeviceManager.addListener]) receive events after they have propagated through
+ // the internal pipeline.
+ // Another way to think of the distinction between internal and external listeners is the
+ // following. Internal listeners are listeners that MediaDataManager depends on, and external
+ // listeners are listeners that depend on MediaDataManager.
+ // TODO(b/159539991#comment5): Move internal listeners to separate package.
+ private val internalListeners: MutableSet<Listener> = mutableSetOf()
private val mediaEntries: LinkedHashMap<String, MediaData> = LinkedHashMap()
- internal var appsBlockedFromResume: MutableSet<String> = Utils.getBlockedMediaApps(context)
- set(value) {
- // Update list
- appsBlockedFromResume.clear()
- appsBlockedFromResume.addAll(value)
-
- // Remove any existing resume players that are now blocked
- appsBlockedFromResume.forEach {
- removeAllForPackage(it)
- }
- }
@Inject
constructor(
@@ -125,9 +126,14 @@ class MediaDataManager(
dumpManager: DumpManager,
broadcastDispatcher: BroadcastDispatcher,
mediaTimeoutListener: MediaTimeoutListener,
- mediaResumeListener: MediaResumeListener
+ mediaResumeListener: MediaResumeListener,
+ mediaSessionBasedFilter: MediaSessionBasedFilter,
+ mediaDeviceManager: MediaDeviceManager,
+ mediaDataCombineLatest: MediaDataCombineLatest,
+ mediaDataFilter: MediaDataFilter
) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory,
broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener,
+ mediaSessionBasedFilter, mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter,
Utils.useMediaResumption(context), Utils.useQsMediaPlayer(context))
private val appChangeReceiver = object : BroadcastReceiver() {
@@ -150,12 +156,26 @@ class MediaDataManager(
init {
dumpManager.registerDumpable(TAG, this)
+
+ // Initialize the internal processing pipeline. The listeners at the front of the pipeline
+ // are set as internal listeners so that they receive events. From there, events are
+ // propagated through the pipeline. The end of the pipeline is currently mediaDataFilter,
+ // so it is responsible for dispatching events to external listeners. To achieve this,
+ // external listeners that are registered with [MediaDataManager.addListener] are actually
+ // registered as listeners to mediaDataFilter.
+ addInternalListener(mediaTimeoutListener)
+ addInternalListener(mediaResumeListener)
+ addInternalListener(mediaSessionBasedFilter)
+ mediaSessionBasedFilter.addListener(mediaDeviceManager)
+ mediaSessionBasedFilter.addListener(mediaDataCombineLatest)
+ mediaDeviceManager.addListener(mediaDataCombineLatest)
+ mediaDataCombineLatest.addListener(mediaDataFilter)
+
+ // Set up links back into the pipeline for listeners that need to send events upstream.
mediaTimeoutListener.timeoutCallback = { token: String, timedOut: Boolean ->
setTimedOut(token, timedOut) }
- addListener(mediaTimeoutListener)
-
mediaResumeListener.setManager(this)
- addListener(mediaResumeListener)
+ mediaDataFilter.mediaDataManager = this
val suspendFilter = IntentFilter(Intent.ACTION_PACKAGES_SUSPENDED)
broadcastDispatcher.registerReceiver(appChangeReceiver, suspendFilter, null, UserHandle.ALL)
@@ -193,10 +213,9 @@ class MediaDataManager(
private fun removeAllForPackage(packageName: String) {
Assert.isMainThread()
- val listenersCopy = listeners.toSet()
val toRemove = mediaEntries.filter { it.value.packageName == packageName }
toRemove.forEach {
- removeEntry(it.key, listenersCopy)
+ removeEntry(it.key)
}
}
@@ -256,15 +275,48 @@ class MediaDataManager(
/**
* Add a listener for changes in this class
*/
- fun addListener(listener: Listener) = listeners.add(listener)
+ fun addListener(listener: Listener) {
+ // mediaDataFilter is the current end of the internal pipeline. Register external
+ // listeners as listeners to it.
+ mediaDataFilter.addListener(listener)
+ }
/**
* Remove a listener for changes in this class
*/
- fun removeListener(listener: Listener) = listeners.remove(listener)
+ fun removeListener(listener: Listener) {
+ // Since mediaDataFilter is the current end of the internal pipelie, external listeners
+ // have been registered to it. So, they need to be removed from it too.
+ mediaDataFilter.removeListener(listener)
+ }
+
+ /**
+ * Add a listener for internal events.
+ */
+ private fun addInternalListener(listener: Listener) = internalListeners.add(listener)
+
+ /**
+ * Notify internal listeners of loaded event.
+ *
+ * External listeners registered with [addListener] will be notified after the event propagates
+ * through the internal listener pipeline.
+ */
+ private fun notifyMediaDataLoaded(key: String, oldKey: String?, info: MediaData) {
+ internalListeners.forEach { it.onMediaDataLoaded(key, oldKey, info) }
+ }
+
+ /**
+ * Notify internal listeners of removed event.
+ *
+ * External listeners registered with [addListener] will be notified after the event propagates
+ * through the internal listener pipeline.
+ */
+ private fun notifyMediaDataRemoved(key: String) {
+ internalListeners.forEach { it.onMediaDataRemoved(key) }
+ }
/**
- * Called whenever the player has been paused or stopped for a while.
+ * Called whenever the player has been paused or stopped for a while, or swiped from QQS.
* This will make the player not active anymore, hiding it from QQS and Keyguard.
* @see MediaData.active
*/
@@ -274,20 +326,28 @@ class MediaDataManager(
return
}
it.active = !timedOut
+ if (DEBUG) Log.d(TAG, "Updating $token timedOut: $timedOut")
onMediaDataLoaded(token, token, it)
}
}
- private fun removeEntry(key: String, listenersCopy: Set<Listener>) {
+ private fun removeEntry(key: String) {
mediaEntries.remove(key)
- listenersCopy.forEach {
- it.onMediaDataRemoved(key)
- }
+ notifyMediaDataRemoved(key)
}
fun dismissMediaData(key: String, delay: Long) {
- val listenersCopy = listeners.toSet()
- foregroundExecutor.executeDelayed({ removeEntry(key, listenersCopy) }, delay)
+ backgroundExecutor.execute {
+ mediaEntries[key]?.let { mediaData ->
+ if (mediaData.isLocalSession) {
+ mediaData.token?.let {
+ val mediaController = mediaControllerFactory.create(it)
+ mediaController.transportControls.stop()
+ }
+ }
+ }
+ }
+ foregroundExecutor.executeDelayed({ removeEntry(key) }, delay)
}
private fun loadMediaDataInBgForResumption(
@@ -306,7 +366,9 @@ class MediaDataManager(
return
}
- Log.d(TAG, "adding track for $userId from browser: $desc")
+ if (DEBUG) {
+ Log.d(TAG, "adding track for $userId from browser: $desc")
+ }
// Album art
var artworkBitmap = desc.iconBitmap
@@ -337,7 +399,8 @@ class MediaDataManager(
) {
val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION)
as MediaSession.Token?
- val metadata = mediaControllerFactory.create(token).metadata
+ val mediaController = mediaControllerFactory.create(token)
+ val metadata = mediaController.metadata
// Foreground and Background colors computed from album art
val notif: Notification = sbn.notification
@@ -406,7 +469,7 @@ class MediaDataManager(
if (actions != null) {
for ((index, action) in actions.withIndex()) {
if (action.getIcon() == null) {
- Log.i(TAG, "No icon for action $index ${action.title}")
+ if (DEBUG) Log.i(TAG, "No icon for action $index ${action.title}")
actionsToShowCollapsed.remove(index)
continue
}
@@ -429,6 +492,10 @@ class MediaDataManager(
}
}
+ val isLocalSession = mediaController.playbackInfo?.playbackType ==
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL ?: true
+ val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null
+
foregroundExecutor.execute {
val resumeAction: Runnable? = mediaEntries[key]?.resumeAction
val hasCheckedForResume = mediaEntries[key]?.hasCheckedForResume == true
@@ -436,8 +503,9 @@ class MediaDataManager(
onMediaDataLoaded(key, oldKey, MediaData(sbn.normalizedUserId, true, bgColor, app,
smallIconDrawable, artist, song, artWorkIcon, actionIcons,
actionsToShowCollapsed, sbn.packageName, token, notif.contentIntent, null,
- active, resumeAction = resumeAction, notificationKey = key,
- hasCheckedForResume = hasCheckedForResume))
+ active, resumeAction = resumeAction, isLocalSession = isLocalSession,
+ notificationKey = key, hasCheckedForResume = hasCheckedForResume,
+ isPlaying = isPlaying, isClearable = sbn.isClearable()))
}
}
@@ -450,7 +518,7 @@ class MediaDataManager(
if (!TextUtils.isEmpty(uriString)) {
val albumArt = loadBitmapFromUri(Uri.parse(uriString))
if (albumArt != null) {
- Log.d(TAG, "loaded art from $uri")
+ if (DEBUG) Log.d(TAG, "loaded art from $uri")
return albumArt
}
}
@@ -481,7 +549,10 @@ class MediaDataManager(
decoder, info, source -> decoder.isMutableRequired = true
}
} catch (e: IOException) {
- e.printStackTrace()
+ Log.e(TAG, "Unable to load bitmap", e)
+ null
+ } catch (e: RuntimeException) {
+ Log.e(TAG, "Unable to load bitmap", e)
null
}
}
@@ -526,19 +597,15 @@ class MediaDataManager(
if (mediaEntries.containsKey(key)) {
// Otherwise this was removed already
mediaEntries.put(key, data)
- val listenersCopy = listeners.toSet()
- listenersCopy.forEach {
- it.onMediaDataLoaded(key, oldKey, data)
- }
+ notifyMediaDataLoaded(key, oldKey, data)
}
}
fun onNotificationRemoved(key: String) {
Assert.isMainThread()
val removed = mediaEntries.remove(key)
- if (useMediaResumption && removed?.resumeAction != null &&
- !isBlockedFromResume(removed?.packageName)) {
- Log.d(TAG, "Not removing $key because resumable")
+ if (useMediaResumption && removed?.resumeAction != null) {
+ if (DEBUG) Log.d(TAG, "Not removing $key because resumable")
// Move to resume key (aka package name) if that key doesn't already exist.
val resumeAction = getResumeMediaAction(removed.resumeAction!!)
val updated = removed.copy(token = null, actions = listOf(resumeAction),
@@ -546,39 +613,22 @@ class MediaDataManager(
val pkg = removed?.packageName
val migrate = mediaEntries.put(pkg, updated) == null
// Notify listeners of "new" controls when migrating or removed and update when not
- val listenersCopy = listeners.toSet()
if (migrate) {
- listenersCopy.forEach {
- it.onMediaDataLoaded(pkg, key, updated)
- }
+ notifyMediaDataLoaded(pkg, key, updated)
} else {
// Since packageName is used for the key of the resumption controls, it is
// possible that another notification has already been reused for the resumption
// controls of this package. In this case, rather than renaming this player as
// packageName, just remove it and then send a update to the existing resumption
// controls.
- listenersCopy.forEach {
- it.onMediaDataRemoved(key)
- }
- listenersCopy.forEach {
- it.onMediaDataLoaded(pkg, pkg, updated)
- }
+ notifyMediaDataRemoved(key)
+ notifyMediaDataLoaded(pkg, pkg, updated)
}
return
}
if (removed != null) {
- val listenersCopy = listeners.toSet()
- listenersCopy.forEach {
- it.onMediaDataRemoved(key)
- }
- }
- }
-
- private fun isBlockedFromResume(packageName: String?): Boolean {
- if (packageName == null) {
- return true
+ notifyMediaDataRemoved(key)
}
- return appsBlockedFromResume.contains(packageName)
}
fun setMediaResumptionEnabled(isEnabled: Boolean) {
@@ -590,17 +640,31 @@ class MediaDataManager(
if (!useMediaResumption) {
// Remove any existing resume controls
- val listenersCopy = listeners.toSet()
val filtered = mediaEntries.filter { !it.value.active }
filtered.forEach {
mediaEntries.remove(it.key)
- listenersCopy.forEach { listener ->
- listener.onMediaDataRemoved(it.key)
- }
+ notifyMediaDataRemoved(it.key)
}
}
}
+ /**
+ * Invoked when the user has dismissed the media carousel
+ */
+ fun onSwipeToDismiss() = mediaDataFilter.onSwipeToDismiss()
+
+ /**
+ * Are there any media notifications active?
+ */
+ fun hasActiveMedia() = mediaDataFilter.hasActiveMedia()
+
+ /**
+ * Are there any media entries we should display?
+ * If resumption is enabled, this will include inactive players
+ * If resumption is disabled, we only want to show active players
+ */
+ fun hasAnyMedia() = mediaDataFilter.hasAnyMedia()
+
interface Listener {
/**
@@ -620,10 +684,10 @@ class MediaDataManager(
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
pw.apply {
- println("listeners: $listeners")
+ println("internalListeners: $internalListeners")
+ println("externalListeners: ${mediaDataFilter.listeners}")
println("mediaEntries: $mediaEntries")
println("useMediaResumption: $useMediaResumption")
- println("appsBlockedFromResume: $appsBlockedFromResume")
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
index 143f8496e7aa..102a4842e3c3 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt
@@ -19,8 +19,12 @@ package com.android.systemui.media
import android.content.Context
import android.media.MediaRouter2Manager
import android.media.session.MediaController
+import androidx.annotation.AnyThread
+import androidx.annotation.MainThread
+import androidx.annotation.WorkerThread
import com.android.settingslib.media.LocalMediaManager
import com.android.settingslib.media.MediaDevice
+import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.Dumpable
import com.android.systemui.dump.DumpManager
@@ -28,25 +32,23 @@ import java.io.FileDescriptor
import java.io.PrintWriter
import java.util.concurrent.Executor
import javax.inject.Inject
-import javax.inject.Singleton
/**
* Provides information about the route (ie. device) where playback is occurring.
*/
-@Singleton
class MediaDeviceManager @Inject constructor(
private val context: Context,
private val localMediaManagerFactory: LocalMediaManagerFactory,
private val mr2manager: MediaRouter2Manager,
@Main private val fgExecutor: Executor,
- private val mediaDataManager: MediaDataManager,
- private val dumpManager: DumpManager
+ @Background private val bgExecutor: Executor,
+ dumpManager: DumpManager
) : MediaDataManager.Listener, Dumpable {
+
private val listeners: MutableSet<Listener> = mutableSetOf()
- private val entries: MutableMap<String, Token> = mutableMapOf()
+ private val entries: MutableMap<String, Entry> = mutableMapOf()
init {
- mediaDataManager.addListener(this)
dumpManager.registerDumpable(javaClass.name, this)
}
@@ -71,7 +73,7 @@ class MediaDeviceManager @Inject constructor(
val controller = data.token?.let {
MediaController(context, it)
}
- entry = Token(key, oldKey, controller,
+ entry = Entry(key, oldKey, controller,
localMediaManagerFactory.create(data.packageName))
entries[key] = entry
entry.start()
@@ -99,6 +101,7 @@ class MediaDeviceManager @Inject constructor(
}
}
+ @MainThread
private fun processDevice(key: String, oldKey: String?, device: MediaDevice?) {
val enabled = device != null
val data = MediaDeviceData(enabled, device?.iconWithoutBackground, device?.name)
@@ -114,12 +117,13 @@ class MediaDeviceManager @Inject constructor(
fun onKeyRemoved(key: String)
}
- private inner class Token(
+ private inner class Entry(
val key: String,
val oldKey: String?,
val controller: MediaController?,
val localMediaManager: LocalMediaManager
) : LocalMediaManager.DeviceCallback {
+
val token
get() = controller?.sessionToken
private var started = false
@@ -127,20 +131,27 @@ class MediaDeviceManager @Inject constructor(
set(value) {
if (!started || value != field) {
field = value
- processDevice(key, oldKey, value)
+ fgExecutor.execute {
+ processDevice(key, oldKey, value)
+ }
}
}
- fun start() {
+
+ @AnyThread
+ fun start() = bgExecutor.execute {
localMediaManager.registerCallback(this)
localMediaManager.startScan()
updateCurrent()
started = true
}
- fun stop() {
+
+ @AnyThread
+ fun stop() = bgExecutor.execute {
started = false
localMediaManager.stopScan()
localMediaManager.unregisterCallback(this)
}
+
fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
val route = controller?.let {
mr2manager.getRoutingSessionForMediaController(it)
@@ -152,14 +163,18 @@ class MediaDeviceManager @Inject constructor(
println(" route=$route")
}
}
- override fun onDeviceListUpdate(devices: List<MediaDevice>?) = fgExecutor.execute {
+
+ override fun onDeviceListUpdate(devices: List<MediaDevice>?) = bgExecutor.execute {
updateCurrent()
}
+
override fun onSelectedDeviceStateChanged(device: MediaDevice, state: Int) {
- fgExecutor.execute {
+ bgExecutor.execute {
updateCurrent()
}
}
+
+ @WorkerThread
private fun updateCurrent() {
val device = localMediaManager.getCurrentConnectedDevice()
controller?.let {
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
index 3598719fcb3a..ce184aa23a57 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt
@@ -14,7 +14,7 @@ import javax.inject.Inject
class MediaHost @Inject constructor(
private val state: MediaHostStateHolder,
private val mediaHierarchyManager: MediaHierarchyManager,
- private val mediaDataFilter: MediaDataFilter,
+ private val mediaDataManager: MediaDataManager,
private val mediaHostStatesManager: MediaHostStatesManager
) : MediaHostState by state {
lateinit var hostView: UniqueObjectHostView
@@ -79,12 +79,12 @@ class MediaHost @Inject constructor(
// be a delay until the views and the controllers are initialized, leaving us
// with either a blank view or the controllers not yet initialized and the
// measuring wrong
- mediaDataFilter.addListener(listener)
+ mediaDataManager.addListener(listener)
updateViewVisibility()
}
override fun onViewDetachedFromWindow(v: View?) {
- mediaDataFilter.removeListener(listener)
+ mediaDataManager.removeListener(listener)
}
})
@@ -113,9 +113,9 @@ class MediaHost @Inject constructor(
private fun updateViewVisibility() {
visible = if (showsOnlyActiveMedia) {
- mediaDataFilter.hasActiveMedia()
+ mediaDataManager.hasActiveMedia()
} else {
- mediaDataFilter.hasAnyMedia()
+ mediaDataManager.hasAnyMedia()
}
val newVisibility = if (visible) View.VISIBLE else View.GONE
if (newVisibility != hostView.visibility) {
@@ -289,4 +289,4 @@ interface MediaHostState {
* Get a copy of this view state, deepcopying all appropriate members
*/
fun copy(): MediaHostState
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
index c41712c4cf10..1ac3034ea7c1 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt
@@ -52,7 +52,6 @@ class MediaResumeListener @Inject constructor(
private var useMediaResumption: Boolean = Utils.useMediaResumption(context)
private val resumeComponents: ConcurrentLinkedQueue<ComponentName> = ConcurrentLinkedQueue()
- private var blockedApps: MutableSet<String> = Utils.getBlockedMediaApps(context)
private lateinit var mediaDataManager: MediaDataManager
@@ -115,18 +114,8 @@ class MediaResumeListener @Inject constructor(
mediaDataManager.setMediaResumptionEnabled(useMediaResumption)
}
}, Settings.Secure.MEDIA_CONTROLS_RESUME)
-
- // Listen to changes in which apps are allowed to persist
- tunerService.addTunable(object : TunerService.Tunable {
- override fun onTuningChanged(key: String?, newValue: String?) {
- blockedApps = Utils.getBlockedMediaApps(context)
- mediaDataManager.appsBlockedFromResume = blockedApps
- }
- }, Settings.Secure.MEDIA_CONTROLS_RESUME_BLOCKED)
}
- fun isResumptionEnabled() = useMediaResumption
-
private fun loadSavedComponents() {
// Make sure list is empty (if we switched users)
resumeComponents.clear()
@@ -153,10 +142,8 @@ class MediaResumeListener @Inject constructor(
}
resumeComponents.forEach {
- if (!blockedApps.contains(it.packageName)) {
- val browser = ResumeMediaBrowser(context, mediaBrowserCallback, it)
- browser.findRecentMedia()
- }
+ val browser = ResumeMediaBrowser(context, mediaBrowserCallback, it)
+ browser.findRecentMedia()
}
}
@@ -165,8 +152,7 @@ class MediaResumeListener @Inject constructor(
// If this had been started from a resume state, disconnect now that it's live
mediaBrowser?.disconnect()
// If we don't have a resume action, check if we haven't already
- if (data.resumeAction == null && !data.hasCheckedForResume &&
- !blockedApps.contains(data.packageName)) {
+ if (data.resumeAction == null && !data.hasCheckedForResume) {
// TODO also check for a media button receiver intended for restarting (b/154127084)
Log.d(TAG, "Checking for service component for " + data.packageName)
val pm = context.packageManager
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt
new file mode 100644
index 000000000000..f695622b943a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.content.ComponentName
+import android.content.Context
+import android.media.session.MediaController
+import android.media.session.MediaController.PlaybackInfo
+import android.media.session.MediaSession
+import android.media.session.MediaSessionManager
+import android.util.Log
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins
+import java.util.concurrent.Executor
+import javax.inject.Inject
+
+private const val TAG = "MediaSessionBasedFilter"
+
+/**
+ * Filters media loaded events for local media sessions while an app is casting.
+ *
+ * When an app is casting there can be one remote media sessions and potentially more local media
+ * sessions. In this situation, there should only be a media object for the remote session. To
+ * achieve this, update events for the local session need to be filtered.
+ */
+class MediaSessionBasedFilter @Inject constructor(
+ context: Context,
+ private val sessionManager: MediaSessionManager,
+ @Main private val foregroundExecutor: Executor,
+ @Background private val backgroundExecutor: Executor
+) : MediaDataManager.Listener {
+
+ private val listeners: MutableSet<MediaDataManager.Listener> = mutableSetOf()
+
+ // Keep track of MediaControllers for a given package to check if an app is casting and it
+ // filter loaded events for local sessions.
+ private val packageControllers: LinkedHashMap<String, MutableList<MediaController>> =
+ LinkedHashMap()
+
+ // Keep track of the key used for the session tokens. This information is used to know when to
+ // dispatch a removed event so that a media object for a local session will be removed.
+ private val keyedTokens: MutableMap<String, MutableSet<MediaSession.Token>> = mutableMapOf()
+
+ // Keep track of which media session tokens have associated notifications.
+ private val tokensWithNotifications: MutableSet<MediaSession.Token> = mutableSetOf()
+
+ private val sessionListener = object : MediaSessionManager.OnActiveSessionsChangedListener {
+ override fun onActiveSessionsChanged(controllers: List<MediaController>) {
+ handleControllersChanged(controllers)
+ }
+ }
+
+ init {
+ backgroundExecutor.execute {
+ val name = ComponentName(context, NotificationListenerWithPlugins::class.java)
+ sessionManager.addOnActiveSessionsChangedListener(sessionListener, name)
+ handleControllersChanged(sessionManager.getActiveSessions(name))
+ }
+ }
+
+ /**
+ * Add a listener for filtered [MediaData] changes
+ */
+ fun addListener(listener: MediaDataManager.Listener) = listeners.add(listener)
+
+ /**
+ * Remove a listener that was registered with addListener
+ */
+ fun removeListener(listener: MediaDataManager.Listener) = listeners.remove(listener)
+
+ /**
+ * May filter loaded events by not passing them along to listeners.
+ *
+ * If an app has only one session with playback type PLAYBACK_TYPE_REMOTE, then assuming that
+ * the app is casting. Sometimes apps will send redundant updates to a local session with
+ * playback type PLAYBACK_TYPE_LOCAL. These updates should be filtered to improve the usability
+ * of the media controls.
+ */
+ override fun onMediaDataLoaded(key: String, oldKey: String?, info: MediaData) {
+ backgroundExecutor.execute {
+ info.token?.let {
+ tokensWithNotifications.add(it)
+ }
+ val isMigration = oldKey != null && key != oldKey
+ if (isMigration) {
+ keyedTokens.remove(oldKey)?.let { removed -> keyedTokens.put(key, removed) }
+ }
+ if (info.token != null) {
+ keyedTokens.get(key)?.let {
+ tokens ->
+ tokens.add(info.token)
+ } ?: run {
+ val tokens = mutableSetOf(info.token)
+ keyedTokens.put(key, tokens)
+ }
+ }
+ // Determine if an app is casting by checking if it has a session with playback type
+ // PLAYBACK_TYPE_REMOTE.
+ val remoteControllers = packageControllers.get(info.packageName)?.filter {
+ it.playbackInfo?.playbackType == PlaybackInfo.PLAYBACK_TYPE_REMOTE
+ }
+ // Limiting search to only apps with a single remote session.
+ val remote = if (remoteControllers?.size == 1) remoteControllers.firstOrNull() else null
+ if (isMigration || remote == null || remote.sessionToken == info.token ||
+ !tokensWithNotifications.contains(remote.sessionToken)) {
+ // Not filtering in this case. Passing the event along to listeners.
+ dispatchMediaDataLoaded(key, oldKey, info)
+ } else {
+ // Filtering this event because the app is casting and the loaded events is for a
+ // local session.
+ Log.d(TAG, "filtering key=$key local=${info.token} remote=${remote?.sessionToken}")
+ // If the local session uses a different notification key, then lets go a step
+ // farther and dismiss the media data so that media controls for the local session
+ // don't hang around while casting.
+ if (!keyedTokens.get(key)!!.contains(remote.sessionToken)) {
+ dispatchMediaDataRemoved(key)
+ }
+ }
+ }
+ }
+
+ override fun onMediaDataRemoved(key: String) {
+ // Queue on background thread to ensure ordering of loaded and removed events is maintained.
+ backgroundExecutor.execute {
+ keyedTokens.remove(key)
+ dispatchMediaDataRemoved(key)
+ }
+ }
+
+ private fun dispatchMediaDataLoaded(key: String, oldKey: String?, info: MediaData) {
+ foregroundExecutor.execute {
+ listeners.toSet().forEach { it.onMediaDataLoaded(key, oldKey, info) }
+ }
+ }
+
+ private fun dispatchMediaDataRemoved(key: String) {
+ foregroundExecutor.execute {
+ listeners.toSet().forEach { it.onMediaDataRemoved(key) }
+ }
+ }
+
+ private fun handleControllersChanged(controllers: List<MediaController>) {
+ packageControllers.clear()
+ controllers.forEach {
+ controller ->
+ packageControllers.get(controller.packageName)?.let {
+ tokens ->
+ tokens.add(controller)
+ } ?: run {
+ val tokens = mutableListOf(controller)
+ packageControllers.put(controller.packageName, tokens)
+ }
+ }
+ tokensWithNotifications.retainAll(controllers.map { it.sessionToken })
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
index d19fc013bd8d..e6abea72da62 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipTaskOrganizer.java
@@ -40,7 +40,6 @@ import android.app.PictureInPictureParams;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
@@ -95,6 +94,36 @@ public class PipTaskOrganizer extends TaskOrganizer implements
private static final int MSG_FINISH_RESIZE = 4;
private static final int MSG_RESIZE_USER = 5;
+ // Not a complete set of states but serves what we want right now.
+ private enum State {
+ UNDEFINED(0),
+ TASK_APPEARED(1),
+ ENTERING_PIP(2),
+ EXITING_PIP(3);
+
+ private final int mStateValue;
+
+ State(int value) {
+ mStateValue = value;
+ }
+
+ private boolean isInPip() {
+ return mStateValue >= TASK_APPEARED.mStateValue
+ && mStateValue != EXITING_PIP.mStateValue;
+ }
+
+ /**
+ * Resize request can be initiated in other component, ignore if we are no longer in PIP,
+ * still waiting for animation or we're exiting from it.
+ *
+ * @return {@code true} if the resize request should be blocked/ignored.
+ */
+ private boolean shouldBlockResizeRequest() {
+ return mStateValue < ENTERING_PIP.mStateValue
+ || mStateValue == EXITING_PIP.mStateValue;
+ }
+ }
+
private final Handler mMainHandler;
private final Handler mUpdateHandler;
private final PipBoundsHandler mPipBoundsHandler;
@@ -104,7 +133,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
private final Rect mLastReportedBounds = new Rect();
private final int mEnterExitAnimationDuration;
private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
- private final Map<IBinder, Configuration> mInitialState = new HashMap<>();
+ private final Map<IBinder, PipWindowConfigurationCompact> mCompactState = new HashMap<>();
private final Divider mSplitDivider;
// These callbacks are called on the update thread
@@ -189,8 +218,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
private ActivityManager.RunningTaskInfo mTaskInfo;
private WindowContainerToken mToken;
private SurfaceControl mLeash;
- private boolean mInPip;
- private boolean mExitingPip;
+ private State mState = State.UNDEFINED;
private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
mSurfaceControlTransactionFactory;
@@ -202,6 +230,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
*/
private boolean mShouldDeferEnteringPip;
+ private @ActivityInfo.ScreenOrientation int mRequestedOrientation;
+
@Inject
public PipTaskOrganizer(Context context, @NonNull PipBoundsHandler boundsHandler,
@NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
@@ -240,11 +270,11 @@ public class PipTaskOrganizer extends TaskOrganizer implements
}
public boolean isInPip() {
- return mInPip;
+ return mState.isInPip();
}
public boolean isDeferringEnterPipAnimation() {
- return mInPip && mShouldDeferEnteringPip;
+ return mState.isInPip() && mShouldDeferEnteringPip;
}
/**
@@ -273,23 +303,26 @@ public class PipTaskOrganizer extends TaskOrganizer implements
* @param animationDurationMs duration in millisecond for the exiting PiP transition
*/
public void exitPip(int animationDurationMs) {
- if (!mInPip || mExitingPip || mToken == null) {
+ if (!mState.isInPip() || mState == State.EXITING_PIP || mToken == null) {
Log.wtf(TAG, "Not allowed to exitPip in current state"
- + " mInPip=" + mInPip + " mExitingPip=" + mExitingPip + " mToken=" + mToken);
+ + " mState=" + mState + " mToken=" + mToken);
return;
}
mPipUiEventLoggerLogger.log(
PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_EXPAND_TO_FULLSCREEN);
- final Configuration initialConfig = mInitialState.remove(mToken.asBinder());
- final boolean orientationDiffers = initialConfig.windowConfiguration.getRotation()
+ final PipWindowConfigurationCompact config = mCompactState.remove(mToken.asBinder());
+ config.syncWithScreenOrientation(mRequestedOrientation,
+ mPipBoundsHandler.getDisplayRotation());
+ final boolean orientationDiffers = config.getRotation()
!= mPipBoundsHandler.getDisplayRotation();
final WindowContainerTransaction wct = new WindowContainerTransaction();
- final Rect destinationBounds = initialConfig.windowConfiguration.getBounds();
+ final Rect destinationBounds = config.getBounds();
final int direction = syncWithSplitScreenBounds(destinationBounds)
? TRANSITION_DIRECTION_TO_SPLIT_SCREEN
: TRANSITION_DIRECTION_TO_FULLSCREEN;
if (orientationDiffers) {
+ mState = State.EXITING_PIP;
// Send started callback though animation is ignored.
sendOnPipTransitionStarted(direction);
// Don't bother doing an animation if the display rotation differs or if it's in
@@ -298,7 +331,6 @@ public class PipTaskOrganizer extends TaskOrganizer implements
WindowOrganizer.applyTransaction(wct);
// Send finished callback though animation is ignored.
sendOnPipTransitionFinished(direction);
- mInPip = false;
} else {
final SurfaceControl.Transaction tx =
mSurfaceControlTransactionFactory.getTransaction();
@@ -317,11 +349,10 @@ public class PipTaskOrganizer extends TaskOrganizer implements
scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
null /* sourceHintRect */, direction, animationDurationMs,
null /* updateBoundsCallback */);
- mInPip = false;
+ mState = State.EXITING_PIP;
}
});
}
- mExitingPip = true;
}
private void applyWindowingModeChangeOnExit(WindowContainerTransaction wct, int direction) {
@@ -338,9 +369,9 @@ public class PipTaskOrganizer extends TaskOrganizer implements
* Removes PiP immediately.
*/
public void removePip() {
- if (!mInPip || mExitingPip || mToken == null) {
+ if (!mState.isInPip() || mToken == null) {
Log.wtf(TAG, "Not allowed to removePip in current state"
- + " mInPip=" + mInPip + " mExitingPip=" + mExitingPip + " mToken=" + mToken);
+ + " mState=" + mState + " mToken=" + mToken);
return;
}
@@ -351,8 +382,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
.setPipAnimationCallback(mPipAnimationCallback)
.setDuration(mEnterExitAnimationDuration)
.start());
- mInitialState.remove(mToken.asBinder());
- mExitingPip = true;
+ mCompactState.remove(mToken.asBinder());
+ mState = State.EXITING_PIP;
}
private void removePipImmediately() {
@@ -374,11 +405,12 @@ public class PipTaskOrganizer extends TaskOrganizer implements
Objects.requireNonNull(info, "Requires RunningTaskInfo");
mTaskInfo = info;
mToken = mTaskInfo.token;
- mInPip = true;
- mExitingPip = false;
+ mState = State.TASK_APPEARED;
mLeash = leash;
- mInitialState.put(mToken.asBinder(), new Configuration(mTaskInfo.configuration));
+ mCompactState.put(mToken.asBinder(),
+ new PipWindowConfigurationCompact(mTaskInfo.configuration.windowConfiguration));
mPictureInPictureParams = mTaskInfo.pictureInPictureParams;
+ mRequestedOrientation = info.requestedOrientation;
mPipUiEventLoggerLogger.setTaskInfo(mTaskInfo);
mPipUiEventLoggerLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_ENTER);
@@ -405,6 +437,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
scheduleAnimateResizePip(currentBounds, destinationBounds, sourceHintRect,
TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
null /* updateBoundsCallback */);
+ mState = State.ENTERING_PIP;
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
enterPipWithAlphaAnimation(destinationBounds, mEnterExitAnimationDuration);
mOneShotAnimationType = ANIM_TYPE_BOUNDS;
@@ -450,6 +483,9 @@ public class PipTaskOrganizer extends TaskOrganizer implements
.setPipAnimationCallback(mPipAnimationCallback)
.setDuration(durationMs)
.start());
+ // mState is set right after the animation is kicked off to block any resize
+ // requests such as offsetPip that may have been called prior to the transition.
+ mState = State.ENTERING_PIP;
}
});
}
@@ -502,7 +538,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
*/
@Override
public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
- if (!mInPip) {
+ if (!mState.isInPip()) {
return;
}
final WindowContainerToken token = info.token;
@@ -513,14 +549,15 @@ public class PipTaskOrganizer extends TaskOrganizer implements
}
mShouldDeferEnteringPip = false;
mPictureInPictureParams = null;
- mInPip = false;
- mExitingPip = false;
+ mState = State.UNDEFINED;
mPipUiEventLoggerLogger.setTaskInfo(null);
}
@Override
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
Objects.requireNonNull(mToken, "onTaskInfoChanged requires valid existing mToken");
+ mRequestedOrientation = info.requestedOrientation;
+ // check PictureInPictureParams for aspect ratio change.
final PictureInPictureParams newParams = info.pictureInPictureParams;
if (newParams == null || !applyPictureInPictureParams(newParams)) {
Log.d(TAG, "Ignored onTaskInfoChanged with PiP param: " + newParams);
@@ -547,7 +584,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
@Override
public void onFixedRotationFinished(int displayId) {
- if (mShouldDeferEnteringPip && mInPip) {
+ if (mShouldDeferEnteringPip && mState.isInPip()) {
final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
mTaskInfo.topActivity, getAspectRatioOrDefault(mPictureInPictureParams),
null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
@@ -558,8 +595,6 @@ public class PipTaskOrganizer extends TaskOrganizer implements
}
/**
- * TODO(b/152809058): consolidate the display info handling logic in SysUI
- *
* @param destinationBoundsOut the current destination bounds will be populated to this param
*/
@SuppressWarnings("unchecked")
@@ -570,7 +605,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
mPipAnimationController.getCurrentAnimator();
if (animator == null || !animator.isRunning()
|| animator.getTransitionDirection() != TRANSITION_DIRECTION_TO_PIP) {
- if (mInPip && fromRotation) {
+ if (mState.isInPip() && fromRotation) {
// If we are rotating while there is a current animation, immediately cancel the
// animation (remove the listeners so we don't trigger the normal finish resize
// call that should only happen on the update thread)
@@ -656,10 +691,10 @@ public class PipTaskOrganizer extends TaskOrganizer implements
private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction,
int durationMs, Consumer<Rect> updateBoundsCallback) {
- if (!mInPip) {
+ if (!mState.isInPip()) {
// TODO: tend to use shouldBlockResizeRequest here as well but need to consider
// the fact that when in exitPip, scheduleAnimateResizePip is executed in the window
- // container transaction callback and we want to set the mExitingPip immediately.
+ // container transaction callback and we want to set the mState immediately.
return;
}
@@ -716,7 +751,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
private void scheduleFinishResizePip(Rect destinationBounds,
@PipAnimationController.TransitionDirection int direction,
Consumer<Rect> updateBoundsCallback) {
- if (shouldBlockResizeRequest()) {
+ if (mState.shouldBlockResizeRequest()) {
return;
}
@@ -735,7 +770,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
mSurfaceTransactionHelper
.crop(tx, mLeash, destinationBounds)
.resetScale(tx, mLeash, destinationBounds)
- .round(tx, mLeash, mInPip);
+ .round(tx, mLeash, mState.isInPip());
return tx;
}
@@ -744,7 +779,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
*/
public void scheduleOffsetPip(Rect originalBounds, int offset, int duration,
Consumer<Rect> updateBoundsCallback) {
- if (shouldBlockResizeRequest()) {
+ if (mState.shouldBlockResizeRequest()) {
return;
}
if (mShouldDeferEnteringPip) {
@@ -789,7 +824,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
mSurfaceTransactionHelper
.crop(tx, mLeash, destinationBounds)
- .round(tx, mLeash, mInPip);
+ .round(tx, mLeash, mState.isInPip());
tx.apply();
}
@@ -921,16 +956,6 @@ public class PipTaskOrganizer extends TaskOrganizer implements
}
/**
- * Resize request can be initiated in other component, ignore if we are no longer in PIP
- * or we're exiting from it.
- *
- * @return {@code true} if the resize request should be blocked/ignored.
- */
- private boolean shouldBlockResizeRequest() {
- return !mInPip || mExitingPip;
- }
-
- /**
* Sync with {@link #mSplitDivider} on destination bounds if PiP is going to split screen.
*
* @param destinationBoundsOut contain the updated destination bounds if applicable
@@ -958,14 +983,14 @@ public class PipTaskOrganizer extends TaskOrganizer implements
pw.println(innerPrefix + "mToken=" + mToken
+ " binder=" + (mToken != null ? mToken.asBinder() : null));
pw.println(innerPrefix + "mLeash=" + mLeash);
- pw.println(innerPrefix + "mInPip=" + mInPip);
+ pw.println(innerPrefix + "mState=" + mState);
pw.println(innerPrefix + "mOneShotAnimationType=" + mOneShotAnimationType);
pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams);
pw.println(innerPrefix + "mLastReportedBounds=" + mLastReportedBounds);
pw.println(innerPrefix + "mInitialState:");
- for (Map.Entry<IBinder, Configuration> e : mInitialState.entrySet()) {
+ for (Map.Entry<IBinder, PipWindowConfigurationCompact> e : mCompactState.entrySet()) {
pw.println(innerPrefix + " binder=" + e.getKey()
- + " winConfig=" + e.getValue().windowConfiguration);
+ + " config=" + e.getValue());
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipUiEventLogger.java b/packages/SystemUI/src/com/android/systemui/pip/PipUiEventLogger.java
index 5e2cd9c111b2..970203578e73 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/PipUiEventLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipUiEventLogger.java
@@ -17,6 +17,7 @@
package com.android.systemui.pip;
import android.app.TaskInfo;
+import android.content.pm.PackageManager;
import com.android.internal.logging.UiEvent;
import com.android.internal.logging.UiEventLogger;
@@ -31,27 +32,49 @@ import javax.inject.Singleton;
@Singleton
public class PipUiEventLogger {
+ private static final int INVALID_PACKAGE_UID = -1;
+
private final UiEventLogger mUiEventLogger;
+ private final PackageManager mPackageManager;
- private TaskInfo mTaskInfo;
+ private String mPackageName;
+ private int mPackageUid = INVALID_PACKAGE_UID;
@Inject
- public PipUiEventLogger(UiEventLogger uiEventLogger) {
+ public PipUiEventLogger(UiEventLogger uiEventLogger, PackageManager packageManager) {
mUiEventLogger = uiEventLogger;
+ mPackageManager = packageManager;
}
public void setTaskInfo(TaskInfo taskInfo) {
- mTaskInfo = taskInfo;
+ if (taskInfo == null) {
+ mPackageName = null;
+ mPackageUid = INVALID_PACKAGE_UID;
+ } else {
+ mPackageName = taskInfo.topActivity.getPackageName();
+ mPackageUid = getUid(mPackageName, taskInfo.userId);
+ }
}
/**
* Sends log via UiEvent, reference go/uievent for how to debug locally
*/
public void log(PipUiEventEnum event) {
- if (mTaskInfo == null) {
+ if (mPackageName == null || mPackageUid == INVALID_PACKAGE_UID) {
return;
}
- mUiEventLogger.log(event, mTaskInfo.userId, mTaskInfo.topActivity.getPackageName());
+ mUiEventLogger.log(event, mPackageUid, mPackageName);
+ }
+
+ private int getUid(String packageName, int userId) {
+ int uid = INVALID_PACKAGE_UID;
+ try {
+ uid = mPackageManager.getApplicationInfoAsUser(
+ packageName, 0 /* ApplicationInfoFlags */, userId).uid;
+ } catch (PackageManager.NameNotFoundException e) {
+ // do nothing.
+ }
+ return uid;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipWindowConfigurationCompact.java b/packages/SystemUI/src/com/android/systemui/pip/PipWindowConfigurationCompact.java
new file mode 100644
index 000000000000..ba104d676cd2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipWindowConfigurationCompact.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.pip;
+
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import android.app.WindowConfiguration;
+import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
+import android.view.Surface;
+
+/**
+ * Compact {@link WindowConfiguration} for PiP usage and supports operations such as rotate.
+ */
+class PipWindowConfigurationCompact {
+ private @Surface.Rotation int mRotation;
+ private Rect mBounds;
+
+ PipWindowConfigurationCompact(WindowConfiguration windowConfiguration) {
+ mRotation = windowConfiguration.getRotation();
+ mBounds = windowConfiguration.getBounds();
+ }
+
+ @Surface.Rotation int getRotation() {
+ return mRotation;
+ }
+
+ Rect getBounds() {
+ return mBounds;
+ }
+
+ void syncWithScreenOrientation(@ActivityInfo.ScreenOrientation int screenOrientation,
+ @Surface.Rotation int displayRotation) {
+ if (mBounds.top != 0 || mBounds.left != 0) {
+ // Supports fullscreen bounds like (0, 0, width, height) only now.
+ return;
+ }
+ boolean rotateNeeded = false;
+ if (ActivityInfo.isFixedOrientationPortrait(screenOrientation)
+ && (mRotation == ROTATION_90 || mRotation == ROTATION_270)) {
+ mRotation = ROTATION_0;
+ rotateNeeded = true;
+ } else if (ActivityInfo.isFixedOrientationLandscape(screenOrientation)
+ && (mRotation == ROTATION_0 || mRotation == ROTATION_180)) {
+ mRotation = ROTATION_90;
+ rotateNeeded = true;
+ } else if (screenOrientation == SCREEN_ORIENTATION_UNSPECIFIED
+ && mRotation != displayRotation) {
+ mRotation = displayRotation;
+ rotateNeeded = true;
+ }
+ if (rotateNeeded) {
+ mBounds.set(0, 0, mBounds.height(), mBounds.width());
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "PipWindowConfigurationCompact(rotation=" + mRotation
+ + " bounds=" + mBounds + ")";
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
index 8a2e4ae11878..9f0b1de21b52 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMotionHelper.java
@@ -26,9 +26,10 @@ import android.os.Debug;
import android.util.Log;
import android.view.Choreographer;
+import androidx.dynamicanimation.animation.AnimationHandler;
+import androidx.dynamicanimation.animation.AnimationHandler.FrameCallbackScheduler;
import androidx.dynamicanimation.animation.SpringForce;
-import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.pip.PipSnapAlgorithm;
import com.android.systemui.pip.PipTaskOrganizer;
import com.android.systemui.util.FloatingContentCoordinator;
@@ -74,9 +75,6 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
/** The region that all of PIP must stay within. */
private final Rect mFloatingAllowedArea = new Rect();
- private final SfVsyncFrameCallbackProvider mSfVsyncFrameProvider =
- new SfVsyncFrameCallbackProvider();
-
/**
* Temporary bounds used when PIP is being dragged or animated. These bounds are applied to PIP
* using {@link PipTaskOrganizer#scheduleUserResizePip}, so that we can animate shrinking into
@@ -94,8 +92,13 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
/** Coordinator instance for resolving conflicts with other floating content. */
private FloatingContentCoordinator mFloatingContentCoordinator;
- /** Callback that re-sizes PIP to the animated bounds. */
- private final Choreographer.FrameCallback mResizePipVsyncCallback;
+ private ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
+ ThreadLocal.withInitial(() -> {
+ FrameCallbackScheduler scheduler = runnable ->
+ Choreographer.getSfInstance().postFrameCallback(t -> runnable.run());
+ AnimationHandler handler = new AnimationHandler(scheduler);
+ return handler;
+ });
/**
* PhysicsAnimator instance for animating {@link #mTemporaryBounds} using physics animations.
@@ -171,16 +174,15 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
mSnapAlgorithm = snapAlgorithm;
mFloatingContentCoordinator = floatingContentCoordinator;
mPipTaskOrganizer.registerPipTransitionCallback(mPipTransitionCallback);
+ mTemporaryBoundsPhysicsAnimator.setCustomAnimationHandler(
+ mSfAnimationHandlerThreadLocal.get());
- mResizePipVsyncCallback = l -> {
+ mResizePipUpdateListener = (target, values) -> {
if (!mTemporaryBounds.isEmpty()) {
mPipTaskOrganizer.scheduleUserResizePip(
mBounds, mTemporaryBounds, null);
}
};
-
- mResizePipUpdateListener = (target, values) ->
- mSfVsyncFrameProvider.postFrameCallback(mResizePipVsyncCallback);
}
@NonNull
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
index ef73aa7cbbfe..badd8835cdd4 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipResizeGestureHandler.java
@@ -80,6 +80,7 @@ public class PipResizeGestureHandler {
private final Context mContext;
private final PipBoundsHandler mPipBoundsHandler;
private final PipMotionHelper mMotionHelper;
+ private final PipMenuActivityController mMenuController;
private final int mDisplayId;
private final Executor mMainExecutor;
private final SysUiState mSysUiState;
@@ -117,13 +118,14 @@ public class PipResizeGestureHandler {
public PipResizeGestureHandler(Context context, PipBoundsHandler pipBoundsHandler,
PipMotionHelper motionHelper, DeviceConfigProxy deviceConfig,
- PipTaskOrganizer pipTaskOrganizer, Function<Rect, Rect> movementBoundsSupplier,
- Runnable updateMovementBoundsRunnable, SysUiState sysUiState,
- PipUiEventLogger pipUiEventLogger) {
+ PipTaskOrganizer pipTaskOrganizer, PipMenuActivityController pipMenuController,
+ Function<Rect, Rect> movementBoundsSupplier, Runnable updateMovementBoundsRunnable,
+ SysUiState sysUiState, PipUiEventLogger pipUiEventLogger) {
mContext = context;
mDisplayId = context.getDisplayId();
mMainExecutor = context.getMainExecutor();
mPipBoundsHandler = pipBoundsHandler;
+ mMenuController = pipMenuController;
mMotionHelper = motionHelper;
mPipTaskOrganizer = pipTaskOrganizer;
mMovementBoundsSupplier = movementBoundsSupplier;
@@ -322,6 +324,10 @@ public class PipResizeGestureHandler {
mInputMonitor.pilferPointers();
}
if (mThresholdCrossed) {
+ if (mMenuController.isMenuActivityVisible()) {
+ mMenuController.hideMenuWithoutResize();
+ mMenuController.hideMenu();
+ }
final Rect currentPipBounds = mMotionHelper.getBounds();
mLastResizeBounds.set(TaskResizingAlgorithm.resizeDrag(x, y,
mDownPoint.x, mDownPoint.y, currentPipBounds, mCtrlType, mMinSize.x,
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 0127ff310b78..11e609b2ffef 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -232,7 +232,7 @@ public class PipTouchHandler {
mSnapAlgorithm, floatingContentCoordinator);
mPipResizeGestureHandler =
new PipResizeGestureHandler(context, pipBoundsHandler, mMotionHelper,
- deviceConfig, pipTaskOrganizer, this::getMovementBounds,
+ deviceConfig, pipTaskOrganizer, menuController, this::getMovementBounds,
this::updateMovementBounds, sysUiState, pipUiEventLogger);
mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler,
() -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(),
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
index acc7f81eb722..8ec3db59117d 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingService.java
@@ -41,6 +41,7 @@ import com.android.internal.logging.UiEventLogger;
import com.android.systemui.R;
import com.android.systemui.dagger.qualifiers.LongRunning;
import com.android.systemui.settings.CurrentUserContextTracker;
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import java.io.IOException;
import java.util.concurrent.Executor;
@@ -70,7 +71,7 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis
private static final String ACTION_SHARE = "com.android.systemui.screenrecord.SHARE";
private final RecordingController mController;
-
+ private final KeyguardDismissUtil mKeyguardDismissUtil;
private ScreenRecordingAudioSource mAudioSource;
private boolean mShowTaps;
private boolean mOriginalShowTaps;
@@ -83,12 +84,13 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis
@Inject
public RecordingService(RecordingController controller, @LongRunning Executor executor,
UiEventLogger uiEventLogger, NotificationManager notificationManager,
- CurrentUserContextTracker userContextTracker) {
+ CurrentUserContextTracker userContextTracker, KeyguardDismissUtil keyguardDismissUtil) {
mController = controller;
mLongExecutor = executor;
mUiEventLogger = uiEventLogger;
mNotificationManager = notificationManager;
mUserContextTracker = userContextTracker;
+ mKeyguardDismissUtil = keyguardDismissUtil;
}
/**
@@ -168,16 +170,17 @@ public class RecordingService extends Service implements MediaRecorder.OnInfoLis
Intent shareIntent = new Intent(Intent.ACTION_SEND)
.setType("video/mp4")
.putExtra(Intent.EXTRA_STREAM, shareUri);
- String shareLabel = getResources().getString(R.string.screenrecord_share_label);
+ mKeyguardDismissUtil.executeWhenUnlocked(() -> {
+ String shareLabel = getResources().getString(R.string.screenrecord_share_label);
+ startActivity(Intent.createChooser(shareIntent, shareLabel)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+ // Remove notification
+ mNotificationManager.cancelAsUser(null, NOTIFICATION_VIEW_ID, currentUser);
+ return false;
+ }, false);
// Close quick shade
sendBroadcast(new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS));
-
- // Remove notification
- mNotificationManager.cancelAsUser(null, NOTIFICATION_VIEW_ID, currentUser);
-
- startActivity(Intent.createChooser(shareIntent, shareLabel)
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
break;
}
return Service.START_STICKY;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index c53523032353..c3c947bc40a8 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -565,7 +565,13 @@ public class GlobalScreenshot implements ViewTreeObserver.OnComputeInternalInset
private void saveScreenshot(Bitmap screenshot, Consumer<Uri> finisher, Rect screenRect,
Insets screenInsets, boolean showFlash) {
- dismissScreenshot("new screenshot requested", true);
+ if (mScreenshotLayout.isAttachedToWindow()) {
+ // if we didn't already dismiss for another reason
+ if (mDismissAnimation == null || !mDismissAnimation.isRunning()) {
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_REENTERED);
+ }
+ dismissScreenshot("new screenshot requested", true);
+ }
mScreenBitmap = screenshot;
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
index 20fa991dcc1f..8535d5708a67 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotEvent.java
@@ -56,7 +56,9 @@ public enum ScreenshotEvent implements UiEventLogger.UiEventEnum {
@UiEvent(doc = "screenshot interaction timed out")
SCREENSHOT_INTERACTION_TIMEOUT(310),
@UiEvent(doc = "screenshot explicitly dismissed")
- SCREENSHOT_EXPLICIT_DISMISSAL(311);
+ SCREENSHOT_EXPLICIT_DISMISSAL(311),
+ @UiEvent(doc = "screenshot reentered for new screenshot")
+ SCREENSHOT_REENTERED(640);
private final int mId;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index 739d30c2a707..8cd82cc77530 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_W
import static com.android.systemui.statusbar.phone.StatusBar.SHOW_LOCKSCREEN_MEDIA_ARTWORK;
import android.annotation.MainThread;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.Notification;
import android.content.Context;
@@ -57,6 +58,7 @@ import com.android.systemui.statusbar.dagger.StatusBarModule;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
import com.android.systemui.statusbar.phone.BiometricUnlockController;
import com.android.systemui.statusbar.phone.KeyguardBypassController;
import com.android.systemui.statusbar.phone.LockscreenWallpaper;
@@ -234,8 +236,17 @@ public class NotificationMediaManager implements Dumpable {
NotificationVisibility visibility,
boolean removedByUser,
int reason) {
- onNotificationRemoved(entry.getKey());
- mediaDataManager.onNotificationRemoved(entry.getKey());
+ removeEntry(entry);
+ }
+ });
+
+ // Pending entries are never inflated, and will never generate a call to onEntryRemoved().
+ // This can happen when notifications are added and canceled before inflation. Add this
+ // separate listener for cleanup, since media inflation occurs onPendingEntryAdded().
+ notificationEntryManager.addCollectionListener(new NotifCollectionListener() {
+ @Override
+ public void onEntryCleanUp(@NonNull NotificationEntry entry) {
+ removeEntry(entry);
}
});
@@ -248,6 +259,11 @@ public class NotificationMediaManager implements Dumpable {
mPropertiesChangedListener);
}
+ private void removeEntry(NotificationEntry entry) {
+ onNotificationRemoved(entry.getKey());
+ mMediaDataManager.onNotificationRemoved(entry.getKey());
+ }
+
/**
* Check if a state should be considered actively playing
* @param state a PlaybackState
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
index 6b8afffa065a..5bee9a762f6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java
@@ -486,6 +486,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
}
}
+ row.showAppOpsIcons(entry.mActiveAppOps);
row.setLastAudiblyAlertedMs(entry.getLastAudiblyAlertedMs());
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
index 84108b196d72..4b244bb18975 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
@@ -76,9 +76,14 @@ public class AppOpsCoordinator implements Coordinator {
// extend the lifetime of foreground notification services to show for at least 5 seconds
mNotifPipeline.addNotificationLifetimeExtender(mForegroundLifetimeExtender);
+ // listen for new notifications to add appOps
+ mNotifPipeline.addCollectionListener(mNotifCollectionListener);
+
// filter out foreground service notifications that aren't necessary anymore
mNotifPipeline.addPreGroupFilter(mNotifFilter);
+ // when appOps change, update any relevant notifications to update appOps for
+ mAppOpsController.addCallback(ForegroundServiceController.APP_OPS, this::onAppOpsChanged);
}
/**
@@ -169,4 +174,82 @@ public class AppOpsCoordinator implements Coordinator {
}
}
};
+
+ /**
+ * Adds appOps to incoming and updating notifications
+ */
+ private NotifCollectionListener mNotifCollectionListener = new NotifCollectionListener() {
+ @Override
+ public void onEntryAdded(NotificationEntry entry) {
+ tagAppOps(entry);
+ }
+
+ @Override
+ public void onEntryUpdated(NotificationEntry entry) {
+ tagAppOps(entry);
+ }
+
+ private void tagAppOps(NotificationEntry entry) {
+ final StatusBarNotification sbn = entry.getSbn();
+ // note: requires that the ForegroundServiceController is updating their appOps first
+ ArraySet<Integer> activeOps =
+ mForegroundServiceController.getAppOps(
+ sbn.getUser().getIdentifier(),
+ sbn.getPackageName());
+
+ entry.mActiveAppOps.clear();
+ if (activeOps != null) {
+ entry.mActiveAppOps.addAll(activeOps);
+ }
+ }
+ };
+
+ private void onAppOpsChanged(int code, int uid, String packageName, boolean active) {
+ mMainExecutor.execute(() -> handleAppOpsChanged(code, uid, packageName, active));
+ }
+
+ /**
+ * Update the appOp for the posted notification associated with the current foreground service
+ *
+ * @param code code for appOp to add/remove
+ * @param uid of user the notification is sent to
+ * @param packageName package that created the notification
+ * @param active whether the appOpCode is active or not
+ */
+ private void handleAppOpsChanged(int code, int uid, String packageName, boolean active) {
+ Assert.isMainThread();
+
+ int userId = UserHandle.getUserId(uid);
+
+ // Update appOps of the app's posted notifications with standard layouts
+ final ArraySet<String> notifKeys =
+ mForegroundServiceController.getStandardLayoutKeys(userId, packageName);
+ if (notifKeys != null) {
+ boolean changed = false;
+ for (int i = 0; i < notifKeys.size(); i++) {
+ final NotificationEntry entry = findNotificationEntryWithKey(notifKeys.valueAt(i));
+ if (entry != null
+ && uid == entry.getSbn().getUid()
+ && packageName.equals(entry.getSbn().getPackageName())) {
+ if (active) {
+ changed |= entry.mActiveAppOps.add(code);
+ } else {
+ changed |= entry.mActiveAppOps.remove(code);
+ }
+ }
+ }
+ if (changed) {
+ mNotifFilter.invalidateList();
+ }
+ }
+ }
+
+ private NotificationEntry findNotificationEntryWithKey(String key) {
+ for (NotificationEntry entry : mNotifPipeline.getAllNotifs()) {
+ if (entry.getKey().equals(key)) {
+ return entry;
+ }
+ }
+ return null;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
new file mode 100644
index 000000000000..28c53dc6d9b2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/AppOpsInfo.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2018 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.notification.row;
+
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+
+/**
+ * The guts of a notification revealed when performing a long press.
+ */
+public class AppOpsInfo extends LinearLayout implements NotificationGuts.GutsContent {
+ private static final String TAG = "AppOpsGuts";
+
+ private PackageManager mPm;
+
+ private String mPkg;
+ private String mAppName;
+ private int mAppUid;
+ private StatusBarNotification mSbn;
+ private ArraySet<Integer> mAppOps;
+ private MetricsLogger mMetricsLogger;
+ private OnSettingsClickListener mOnSettingsClickListener;
+ private NotificationGuts mGutsContainer;
+ private UiEventLogger mUiEventLogger;
+
+ private OnClickListener mOnOk = v -> {
+ mGutsContainer.closeControls(v, false);
+ };
+
+ public AppOpsInfo(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public interface OnSettingsClickListener {
+ void onClick(View v, String pkg, int uid, ArraySet<Integer> ops);
+ }
+
+ public void bindGuts(final PackageManager pm,
+ final OnSettingsClickListener onSettingsClick,
+ final StatusBarNotification sbn,
+ final UiEventLogger uiEventLogger,
+ ArraySet<Integer> activeOps) {
+ mPkg = sbn.getPackageName();
+ mSbn = sbn;
+ mPm = pm;
+ mAppName = mPkg;
+ mOnSettingsClickListener = onSettingsClick;
+ mAppOps = activeOps;
+ mUiEventLogger = uiEventLogger;
+
+ bindHeader();
+ bindPrompt();
+ bindButtons();
+
+ logUiEvent(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_OPEN);
+ mMetricsLogger = new MetricsLogger();
+ mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, true);
+ }
+
+ private void bindHeader() {
+ // Package name
+ Drawable pkgicon = null;
+ ApplicationInfo info;
+ try {
+ info = mPm.getApplicationInfo(mPkg,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE);
+ if (info != null) {
+ mAppUid = mSbn.getUid();
+ mAppName = String.valueOf(mPm.getApplicationLabel(info));
+ pkgicon = mPm.getApplicationIcon(info);
+ }
+ } catch (PackageManager.NameNotFoundException e) {
+ // app is gone, just show package name and generic icon
+ pkgicon = mPm.getDefaultActivityIcon();
+ }
+ ((ImageView) findViewById(R.id.pkgicon)).setImageDrawable(pkgicon);
+ ((TextView) findViewById(R.id.pkgname)).setText(mAppName);
+ }
+
+ private void bindPrompt() {
+ final TextView prompt = findViewById(R.id.prompt);
+ prompt.setText(getPrompt());
+ }
+
+ private void bindButtons() {
+ View settings = findViewById(R.id.settings);
+ settings.setOnClickListener((View view) -> {
+ mOnSettingsClickListener.onClick(view, mPkg, mAppUid, mAppOps);
+ });
+ TextView ok = findViewById(R.id.ok);
+ ok.setOnClickListener(mOnOk);
+ ok.setAccessibilityDelegate(mGutsContainer.getAccessibilityDelegate());
+ }
+
+ private String getPrompt() {
+ if (mAppOps == null || mAppOps.size() == 0) {
+ return "";
+ } else if (mAppOps.size() == 1) {
+ if (mAppOps.contains(AppOpsManager.OP_CAMERA)) {
+ return mContext.getString(R.string.appops_camera);
+ } else if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) {
+ return mContext.getString(R.string.appops_microphone);
+ } else {
+ return mContext.getString(R.string.appops_overlay);
+ }
+ } else if (mAppOps.size() == 2) {
+ if (mAppOps.contains(AppOpsManager.OP_CAMERA)) {
+ if (mAppOps.contains(AppOpsManager.OP_RECORD_AUDIO)) {
+ return mContext.getString(R.string.appops_camera_mic);
+ } else {
+ return mContext.getString(R.string.appops_camera_overlay);
+ }
+ } else {
+ return mContext.getString(R.string.appops_mic_overlay);
+ }
+ } else {
+ return mContext.getString(R.string.appops_camera_mic_overlay);
+ }
+ }
+
+ @Override
+ public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+ super.onInitializeAccessibilityEvent(event);
+ if (mGutsContainer != null &&
+ event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+ if (mGutsContainer.isExposed()) {
+ event.getText().add(mContext.getString(
+ R.string.notification_channel_controls_opened_accessibility, mAppName));
+ } else {
+ event.getText().add(mContext.getString(
+ R.string.notification_channel_controls_closed_accessibility, mAppName));
+ }
+ }
+ }
+
+ @Override
+ public void setGutsParent(NotificationGuts guts) {
+ mGutsContainer = guts;
+ }
+
+ @Override
+ public boolean willBeRemoved() {
+ return false;
+ }
+
+ @Override
+ public boolean shouldBeSaved() {
+ return false;
+ }
+
+ @Override
+ public boolean needsFalsingProtection() {
+ return false;
+ }
+
+ @Override
+ public View getContentView() {
+ return this;
+ }
+
+ @Override
+ public boolean handleCloseControls(boolean save, boolean force) {
+ logUiEvent(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_CLOSE);
+ if (mMetricsLogger != null) {
+ mMetricsLogger.visibility(MetricsEvent.APP_OPS_GUTS, false);
+ }
+ return false;
+ }
+
+ @Override
+ public int getActualHeight() {
+ return getHeight();
+ }
+
+ private void logUiEvent(NotificationAppOpsEvent event) {
+ if (mSbn != null) {
+ mUiEventLogger.logWithInstanceId(event,
+ mSbn.getUid(), mSbn.getPackageName(), mSbn.getInstanceId());
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 8ead7bf2322f..94e12e82f850 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -239,6 +239,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private boolean mShowNoBackground;
private ExpandableNotificationRow mNotificationParent;
private OnExpandClickListener mOnExpandClickListener;
+ private View.OnClickListener mOnAppOpsClickListener;
// Listener will be called when receiving a long click event.
// Use #setLongPressPosition to optionally assign positional data with the long press.
@@ -1142,6 +1143,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
items.add(NotificationMenuRow.createPartialConversationItem(mContext));
items.add(NotificationMenuRow.createInfoItem(mContext));
items.add(NotificationMenuRow.createSnoozeItem(mContext));
+ items.add(NotificationMenuRow.createAppOpsItem(mContext));
mMenuRow.setMenuItems(items);
}
if (existed) {
@@ -1607,6 +1609,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
RowContentBindStage rowContentBindStage,
OnExpandClickListener onExpandClickListener,
NotificationMediaManager notificationMediaManager,
+ OnAppOpsClickListener onAppOpsClickListener,
FalsingManager falsingManager,
StatusBarStateController statusBarStateController,
PeopleNotificationIdentifier peopleNotificationIdentifier) {
@@ -1626,6 +1629,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mRowContentBindStage = rowContentBindStage;
mOnExpandClickListener = onExpandClickListener;
mMediaManager = notificationMediaManager;
+ setAppOpsOnClickListener(onAppOpsClickListener);
mFalsingManager = falsingManager;
mStatusbarStateController = statusBarStateController;
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
@@ -1682,6 +1686,14 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
requestLayout();
}
+ public void showAppOpsIcons(ArraySet<Integer> activeOps) {
+ if (mIsSummaryWithChildren) {
+ mChildrenContainer.showAppOpsIcons(activeOps);
+ }
+ mPrivateLayout.showAppOpsIcons(activeOps);
+ mPublicLayout.showAppOpsIcons(activeOps);
+ }
+
/** Sets the last time the notification being displayed audibly alerted the user. */
public void setLastAudiblyAlertedMs(long lastAudiblyAlertedMs) {
if (NotificationUtils.useNewInterruptionModel(mContext)) {
@@ -1710,6 +1722,24 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mPublicLayout.setRecentlyAudiblyAlerted(audiblyAlertedRecently);
}
+ public View.OnClickListener getAppOpsOnClickListener() {
+ return mOnAppOpsClickListener;
+ }
+
+ void setAppOpsOnClickListener(ExpandableNotificationRow.OnAppOpsClickListener l) {
+ mOnAppOpsClickListener = v -> {
+ createMenu();
+ NotificationMenuRowPlugin provider = getProvider();
+ if (provider == null) {
+ return;
+ }
+ MenuItem menuItem = provider.getAppOpsMenuItem(mContext);
+ if (menuItem != null) {
+ l.onClick(this, v.getWidth() / 2, v.getHeight() / 2, menuItem);
+ }
+ };
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
index b132caf56265..7a6109d2ce78 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java
@@ -63,6 +63,7 @@ public class ExpandableNotificationRowController {
private final ExpandableNotificationRow.ExpansionLogger mExpansionLogger =
this::logNotificationExpansion;
+ private final ExpandableNotificationRow.OnAppOpsClickListener mOnAppOpsClickListener;
private final NotificationGutsManager mNotificationGutsManager;
private Runnable mOnDismissRunnable;
private final FalsingManager mFalsingManager;
@@ -100,6 +101,7 @@ public class ExpandableNotificationRowController {
mStatusBarStateController = statusBarStateController;
mNotificationGutsManager = notificationGutsManager;
mOnDismissRunnable = onDismissRunnable;
+ mOnAppOpsClickListener = mNotificationGutsManager::openGuts;
mAllowLongPress = allowLongPress;
mFalsingManager = falsingManager;
mPeopleNotificationIdentifier = peopleNotificationIdentifier;
@@ -120,6 +122,7 @@ public class ExpandableNotificationRowController {
mRowContentBindStage,
mOnExpandClickListener,
mMediaManager,
+ mOnAppOpsClickListener,
mFalsingManager,
mStatusBarStateController,
mPeopleNotificationIdentifier
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 41a9b187129c..1f5b063b0aa2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -1567,6 +1567,18 @@ public class NotificationContentView extends FrameLayout {
return header;
}
+ public void showAppOpsIcons(ArraySet<Integer> activeOps) {
+ if (mContractedChild != null) {
+ mContractedWrapper.showAppOpsIcons(activeOps);
+ }
+ if (mExpandedChild != null) {
+ mExpandedWrapper.showAppOpsIcons(activeOps);
+ }
+ if (mHeadsUpChild != null) {
+ mHeadsUpWrapper.showAppOpsIcons(activeOps);
+ }
+ }
+
/** Sets whether the notification being displayed audibly alerted the user. */
public void setRecentlyAudiblyAlerted(boolean audiblyAlerted) {
if (mContractedChild != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index f543db74d91a..25a0ea515ea3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -42,6 +42,8 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ShortcutInfo;
import android.content.pm.ShortcutManager;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -539,12 +541,21 @@ public class NotificationConversationInfo extends LinearLayout implements
&& Settings.Global.getInt(mContext.getContentResolver(),
NOTIFICATION_BUBBLES, 0) == 1;
+ Drawable person = mIconFactory.getBaseIconDrawable(mShortcutInfo);
+ if (person == null) {
+ person = mContext.getDrawable(R.drawable.ic_person).mutate();
+ TypedArray ta = mContext.obtainStyledAttributes(new int[]{android.R.attr.colorAccent});
+ int colorAccent = ta.getColor(0, 0);
+ ta.recycle();
+ person.setTint(colorAccent);
+ }
+
PriorityOnboardingDialogController controller = mBuilderProvider.get()
.setContext(mUserContext)
.setView(onboardingView)
.setIgnoresDnd(ignoreDnd)
.setShowsAsBubble(showAsBubble)
- .setIcon(mIconFactory.getBaseIconDrawable(mShortcutInfo))
+ .setIcon(person)
.setBadge(mIconFactory.getAppBadge(
mPackageName, UserHandle.getUserId(mSbn.getUid())))
.setOnSettingsClick(mOnConversationSettingsClickListener)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 3eed18a90836..24883f51a984 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -264,6 +264,8 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
try {
if (gutsView instanceof NotificationSnooze) {
initializeSnoozeView(row, (NotificationSnooze) gutsView);
+ } else if (gutsView instanceof AppOpsInfo) {
+ initializeAppOpsInfo(row, (AppOpsInfo) gutsView);
} else if (gutsView instanceof NotificationInfo) {
initializeNotificationInfo(row, (NotificationInfo) gutsView);
} else if (gutsView instanceof NotificationConversationInfo) {
@@ -301,6 +303,36 @@ public class NotificationGutsManager implements Dumpable, NotificationLifetimeEx
}
/**
+ * Sets up the {@link AppOpsInfo} inside the notification row's guts.
+ *
+ * @param row view to set up the guts for
+ * @param appOpsInfoView view to set up/bind within {@code row}
+ */
+ private void initializeAppOpsInfo(
+ final ExpandableNotificationRow row,
+ AppOpsInfo appOpsInfoView) {
+ NotificationGuts guts = row.getGuts();
+ StatusBarNotification sbn = row.getEntry().getSbn();
+ UserHandle userHandle = sbn.getUser();
+ PackageManager pmUser = StatusBar.getPackageManagerForUser(mContext,
+ userHandle.getIdentifier());
+
+ AppOpsInfo.OnSettingsClickListener onSettingsClick =
+ (View v, String pkg, int uid, ArraySet<Integer> ops) -> {
+ mUiEventLogger.logWithInstanceId(
+ NotificationAppOpsEvent.NOTIFICATION_APP_OPS_SETTINGS_CLICK,
+ sbn.getUid(), sbn.getPackageName(), sbn.getInstanceId());
+ mMetricsLogger.action(MetricsProto.MetricsEvent.ACTION_OPS_GUTS_SETTINGS);
+ guts.resetFalsingCheck();
+ startAppOpsSettingsActivity(pkg, uid, ops, row);
+ };
+ if (!row.getEntry().mActiveAppOps.isEmpty()) {
+ appOpsInfoView.bindGuts(pmUser, onSettingsClick, sbn, mUiEventLogger,
+ row.getEntry().mActiveAppOps);
+ }
+ }
+
+ /**
* Sets up the {@link NotificationInfo} inside the notification row's guts.
* @param row view to set up the guts for
* @param notificationInfoView view to set up/bind within {@code row}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index a167925a6358..5e1e3b255867 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -76,6 +76,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
private Context mContext;
private FrameLayout mMenuContainer;
private NotificationMenuItem mInfoItem;
+ private MenuItem mAppOpsItem;
private MenuItem mSnoozeItem;
private ArrayList<MenuItem> mLeftMenuItems;
private ArrayList<MenuItem> mRightMenuItems;
@@ -137,6 +138,11 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
}
@Override
+ public MenuItem getAppOpsMenuItem(Context context) {
+ return mAppOpsItem;
+ }
+
+ @Override
public MenuItem getSnoozeMenuItem(Context context) {
return mSnoozeItem;
}
@@ -258,6 +264,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
// Only show snooze for non-foreground notifications, and if the setting is on
mSnoozeItem = createSnoozeItem(mContext);
}
+ mAppOpsItem = createAppOpsItem(mContext);
NotificationEntry entry = mParent.getEntry();
int personNotifType = mPeopleNotificationIdentifier
.getPeopleNotificationType(entry.getSbn(), entry.getRanking());
@@ -273,6 +280,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
mRightMenuItems.add(mSnoozeItem);
}
mRightMenuItems.add(mInfoItem);
+ mRightMenuItems.add(mAppOpsItem);
mLeftMenuItems.addAll(mRightMenuItems);
populateMenuViews();
@@ -680,6 +688,14 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
R.drawable.ic_settings);
}
+ static MenuItem createAppOpsItem(Context context) {
+ AppOpsInfo appOpsContent = (AppOpsInfo) LayoutInflater.from(context).inflate(
+ R.layout.app_ops_info, null, false);
+ MenuItem info = new NotificationMenuItem(context, null, appOpsContent,
+ -1 /*don't show in slow swipe menu */);
+ return info;
+ }
+
private void addMenuView(MenuItem item, ViewGroup parent) {
View menuView = item.getMenuView();
if (menuView != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
index 86fc352f6fe9..c747a7c300b7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationHeaderViewWrapper.java
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar.notification.row.wrapper;
import static com.android.systemui.statusbar.notification.TransformState.TRANSFORM_Y;
+import android.app.AppOpsManager;
import android.app.Notification;
import android.content.Context;
import android.util.ArraySet;
@@ -63,6 +64,10 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
private TextView mHeaderText;
private TextView mAppNameText;
private ImageView mWorkProfileImage;
+ private View mCameraIcon;
+ private View mMicIcon;
+ private View mOverlayIcon;
+ private View mAppOps;
private View mAudiblyAlertedIcon;
private FrameLayout mIconContainer;
@@ -103,6 +108,7 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
}
}, TRANSFORMING_VIEW_TITLE);
resolveHeaderViews();
+ addAppOpsOnClickListener(row);
}
protected void resolveHeaderViews() {
@@ -113,6 +119,10 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
mExpandButton = mView.findViewById(com.android.internal.R.id.expand_button);
mWorkProfileImage = mView.findViewById(com.android.internal.R.id.profile_badge);
mNotificationHeader = mView.findViewById(com.android.internal.R.id.notification_header);
+ mCameraIcon = mView.findViewById(com.android.internal.R.id.camera);
+ mMicIcon = mView.findViewById(com.android.internal.R.id.mic);
+ mOverlayIcon = mView.findViewById(com.android.internal.R.id.overlay);
+ mAppOps = mView.findViewById(com.android.internal.R.id.app_ops);
mAudiblyAlertedIcon = mView.findViewById(com.android.internal.R.id.alerted_icon);
if (mNotificationHeader != null) {
mNotificationHeader.setShowExpandButtonAtEnd(mShowExpandButtonAtEnd);
@@ -120,6 +130,38 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
}
}
+ private void addAppOpsOnClickListener(ExpandableNotificationRow row) {
+ View.OnClickListener listener = row.getAppOpsOnClickListener();
+ if (mNotificationHeader != null) {
+ mNotificationHeader.setAppOpsOnClickListener(listener);
+ }
+ if (mAppOps != null) {
+ mAppOps.setOnClickListener(listener);
+ }
+ }
+
+ /**
+ * Shows or hides 'app op in use' icons based on app usage.
+ */
+ @Override
+ public void showAppOpsIcons(ArraySet<Integer> appOps) {
+ if (appOps == null) {
+ return;
+ }
+ if (mOverlayIcon != null) {
+ mOverlayIcon.setVisibility(appOps.contains(AppOpsManager.OP_SYSTEM_ALERT_WINDOW)
+ ? View.VISIBLE : View.GONE);
+ }
+ if (mCameraIcon != null) {
+ mCameraIcon.setVisibility(appOps.contains(AppOpsManager.OP_CAMERA)
+ ? View.VISIBLE : View.GONE);
+ }
+ if (mMicIcon != null) {
+ mMicIcon.setVisibility(appOps.contains(AppOpsManager.OP_RECORD_AUDIO)
+ ? View.VISIBLE : View.GONE);
+ }
+ }
+
@Override
public void onContentUpdated(ExpandableNotificationRow row) {
super.onContentUpdated(row);
@@ -243,6 +285,15 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TITLE,
mHeaderText);
}
+ if (mCameraIcon != null) {
+ mTransformationHelper.addViewTransformingToSimilar(mCameraIcon);
+ }
+ if (mMicIcon != null) {
+ mTransformationHelper.addViewTransformingToSimilar(mMicIcon);
+ }
+ if (mOverlayIcon != null) {
+ mTransformationHelper.addViewTransformingToSimilar(mOverlayIcon);
+ }
if (mAudiblyAlertedIcon != null) {
mTransformationHelper.addViewTransformingToSimilar(mAudiblyAlertedIcon);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
index 4bf279444462..30080e3d8cc2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java
@@ -96,6 +96,14 @@ public abstract class NotificationViewWrapper implements TransformableView {
public void onContentUpdated(ExpandableNotificationRow row) {
}
+ /**
+ * Show a set of app opp icons in the layout.
+ *
+ * @param appOps which app ops to show
+ */
+ public void showAppOpsIcons(ArraySet<Integer> appOps) {
+ }
+
public void onReinflated() {
if (shouldClearBackgroundOnReapply()) {
mBackgroundColor = 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index 5edcde1cd3c7..99691b710cc2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -1302,6 +1302,20 @@ public class NotificationChildrenContainer extends ViewGroup {
mCurrentHeaderTranslation = (int) ((1.0f - headerVisibleAmount) * mTranslationForHeader);
}
+ /**
+ * Show a set of app opp icons in the layout.
+ *
+ * @param appOps which app ops to show
+ */
+ public void showAppOpsIcons(ArraySet<Integer> appOps) {
+ if (mNotificationHeaderWrapper != null) {
+ mNotificationHeaderWrapper.showAppOpsIcons(appOps);
+ }
+ if (mNotificationHeaderWrapperLowPriority != null) {
+ mNotificationHeaderWrapperLowPriority.showAppOpsIcons(appOps);
+ }
+ }
+
public void setRecentlyAudiblyAlerted(boolean audiblyAlertedRecently) {
if (mNotificationHeaderWrapper != null) {
mNotificationHeaderWrapper.setRecentlyAudiblyAlerted(audiblyAlertedRecently);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
index 23d03a4b225a..e1ff9a236b02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonDrawable.java
@@ -172,6 +172,24 @@ public class KeyButtonDrawable extends Drawable {
}
@Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ boolean changed = super.setVisible(visible, restart);
+ if (changed) {
+ // End any existing animations when the visibility changes
+ jumpToCurrentState();
+ }
+ return changed;
+ }
+
+ @Override
+ public void jumpToCurrentState() {
+ super.jumpToCurrentState();
+ if (mAnimatedDrawable != null) {
+ mAnimatedDrawable.jumpToCurrentState();
+ }
+ }
+
+ @Override
public void setAlpha(int alpha) {
mState.mAlpha = alpha;
mIconPaint.setAlpha(alpha);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
index 2d8784dc41bd..9e1485dba8bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
@@ -225,6 +225,16 @@ public class KeyButtonRipple extends Drawable {
}
@Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ boolean changed = super.setVisible(visible, restart);
+ if (changed) {
+ // End any existing animations when the visibility changes
+ jumpToCurrentState();
+ }
+ return changed;
+ }
+
+ @Override
public void jumpToCurrentState() {
endAnimations("jumpToCurrentState", false /* cancel */);
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 2512257fdc19..9ad2aa257aa0 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -63,8 +63,7 @@ public class TunerServiceImpl extends TunerService {
private static final String[] RESET_BLACKLIST = new String[] {
QSTileHost.TILES_SETTING,
Settings.Secure.DOZE_ALWAYS_ON,
- Settings.Secure.MEDIA_CONTROLS_RESUME,
- Secure.MEDIA_CONTROLS_RESUME_BLOCKED
+ Settings.Secure.MEDIA_CONTROLS_RESUME
};
private final Observer mObserver = new Observer();
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index 21f7a85b3277..9e3fcc401ffa 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -21,15 +21,12 @@ import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.provider.Settings;
-import android.text.TextUtils;
import android.view.View;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.CommandQueue;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
import java.util.function.Consumer;
public class Utils {
@@ -144,21 +141,4 @@ public class Utils {
Settings.Secure.MEDIA_CONTROLS_RESUME, 1);
return useQsMediaPlayer(context) && flag > 0;
}
-
- /**
- * Get the set of apps for which the user has manually disabled resumption.
- */
- public static Set<String> getBlockedMediaApps(Context context) {
- String list = Settings.Secure.getString(context.getContentResolver(),
- Settings.Secure.MEDIA_CONTROLS_RESUME_BLOCKED);
- if (TextUtils.isEmpty(list)) {
- return new HashSet<>();
- }
- String[] names = list.split(":");
- Set<String> apps = new HashSet<>(names.length);
- for (String s : names) {
- apps.add(s);
- }
- return apps;
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
index 016f4de724b6..2a5424ce4ef7 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
@@ -20,6 +20,7 @@ import android.os.Looper
import android.util.ArrayMap
import android.util.Log
import android.view.View
+import androidx.dynamicanimation.animation.AnimationHandler
import androidx.dynamicanimation.animation.DynamicAnimation
import androidx.dynamicanimation.animation.FlingAnimation
import androidx.dynamicanimation.animation.FloatPropertyCompat
@@ -124,6 +125,12 @@ class PhysicsAnimator<T> private constructor (target: T) {
private var defaultFling: FlingConfig = globalDefaultFling
/**
+ * AnimationHandler to use if it need custom AnimationHandler, if this is null, it will use
+ * the default AnimationHandler in the DynamicAnimation.
+ */
+ private var customAnimationHandler: AnimationHandler? = null
+
+ /**
* Internal listeners that respond to DynamicAnimations updating and ending, and dispatch to
* the listeners provided via [addUpdateListener] and [addEndListener]. This allows us to add
* just one permanent update and end listener to the DynamicAnimations.
@@ -447,6 +454,14 @@ class PhysicsAnimator<T> private constructor (target: T) {
this.defaultFling = defaultFling
}
+ /**
+ * Set the custom AnimationHandler for all aniatmion in this animator. Set this with null for
+ * restoring to default AnimationHandler.
+ */
+ fun setCustomAnimationHandler(handler: AnimationHandler) {
+ this.customAnimationHandler = handler
+ }
+
/** Starts the animations! */
fun start() {
startAction()
@@ -501,10 +516,13 @@ class PhysicsAnimator<T> private constructor (target: T) {
// springs) on this property before flinging.
cancel(animatedProperty)
+ // Apply the custom animation handler if it not null
+ val flingAnim = getFlingAnimation(animatedProperty, target)
+ flingAnim.animationHandler =
+ customAnimationHandler ?: flingAnim.animationHandler
+
// Apply the configuration and start the animation.
- getFlingAnimation(animatedProperty, target)
- .also { flingConfig.applyToAnimation(it) }
- .start()
+ flingAnim.also { flingConfig.applyToAnimation(it) }.start()
}
}
@@ -516,6 +534,21 @@ class PhysicsAnimator<T> private constructor (target: T) {
if (flingConfig == null) {
// Apply the configuration and start the animation.
val springAnim = getSpringAnimation(animatedProperty, target)
+
+ // If customAnimationHander is exist and has not been set to the animation,
+ // it should set here.
+ if (customAnimationHandler != null &&
+ springAnim.animationHandler != customAnimationHandler) {
+ // Cancel the animation before set animation handler
+ if (springAnim.isRunning) {
+ cancel(animatedProperty)
+ }
+ // Apply the custom animation handler if it not null
+ springAnim.animationHandler =
+ customAnimationHandler ?: springAnim.animationHandler
+ }
+
+ // Apply the configuration and start the animation.
springConfig.applyToAnimation(springAnim)
animationStartActions.add(springAnim::start)
} else {
@@ -570,10 +603,13 @@ class PhysicsAnimator<T> private constructor (target: T) {
}
}
+ // Apply the custom animation handler if it not null
+ val springAnim = getSpringAnimation(animatedProperty, target)
+ springAnim.animationHandler =
+ customAnimationHandler ?: springAnim.animationHandler
+
// Apply the configuration and start the spring animation.
- getSpringAnimation(animatedProperty, target)
- .also { springConfig.applyToAnimation(it) }
- .start()
+ springAnim.also { springConfig.applyToAnimation(it) }.start()
}
}
})
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index e967a5d607eb..60f0cd9da5f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -82,7 +82,8 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
allowTestableLooperAsMainThread();
MockitoAnnotations.initMocks(this);
- mFsc = new ForegroundServiceController(mAppOpsController, mMainHandler);
+ mFsc = new ForegroundServiceController(
+ mEntryManager, mAppOpsController, mMainHandler);
mListener = new ForegroundServiceNotificationListener(
mContext, mFsc, mEntryManager, mNotifPipeline,
mock(ForegroundServiceLifetimeExtender.class), mClock);
@@ -114,6 +115,85 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
}
@Test
+ public void testAppOps_appOpChangedBeforeNotificationExists() {
+ // GIVEN app op exists, but notification doesn't exist in NEM yet
+ NotificationEntry entry = createFgEntry();
+ mFsc.onAppOpChanged(
+ AppOpsManager.OP_CAMERA,
+ entry.getSbn().getUid(),
+ entry.getSbn().getPackageName(),
+ true);
+ assertFalse(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+
+ // WHEN the notification is added
+ mEntryListener.onPendingEntryAdded(entry);
+
+ // THEN the app op is added to the entry
+ Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+ }
+
+ @Test
+ public void testAppOps_appOpAddedToForegroundNotif() {
+ // GIVEN a notification associated with a foreground service
+ NotificationEntry entry = addFgEntry();
+ when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(entry);
+
+ // WHEN we are notified of a new app op for this notification
+ mFsc.onAppOpChanged(
+ AppOpsManager.OP_CAMERA,
+ entry.getSbn().getUid(),
+ entry.getSbn().getPackageName(),
+ true);
+
+ // THEN the app op is added to the entry
+ Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+
+ // THEN notification views are updated since the notification is visible
+ verify(mEntryManager, times(1)).updateNotifications(anyString());
+ }
+
+ @Test
+ public void testAppOpsAlreadyAdded() {
+ // GIVEN a foreground service associated notification that already has the correct app op
+ NotificationEntry entry = addFgEntry();
+ entry.mActiveAppOps.add(AppOpsManager.OP_CAMERA);
+ when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(entry);
+
+ // WHEN we are notified of the same app op for this notification
+ mFsc.onAppOpChanged(
+ AppOpsManager.OP_CAMERA,
+ entry.getSbn().getUid(),
+ entry.getSbn().getPackageName(),
+ true);
+
+ // THEN the app op still exists in the notification entry
+ Assert.assertTrue(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+
+ // THEN notification views aren't updated since nothing changed
+ verify(mEntryManager, never()).updateNotifications(anyString());
+ }
+
+ @Test
+ public void testAppOps_appOpNotAddedToUnrelatedNotif() {
+ // GIVEN no notification entries correspond to the newly updated appOp
+ NotificationEntry entry = addFgEntry();
+ when(mEntryManager.getPendingOrActiveNotif(entry.getKey())).thenReturn(null);
+
+ // WHEN a new app op is detected
+ mFsc.onAppOpChanged(
+ AppOpsManager.OP_CAMERA,
+ entry.getSbn().getUid(),
+ entry.getSbn().getPackageName(),
+ true);
+
+ // THEN we won't see appOps on the entry
+ Assert.assertFalse(entry.mActiveAppOps.contains(AppOpsManager.OP_CAMERA));
+
+ // THEN notification views aren't updated since nothing changed
+ verify(mEntryManager, never()).updateNotifications(anyString());
+ }
+
+ @Test
public void testAppOpsCRUD() {
// no crash on remove that doesn't exist
mFsc.onAppOpChanged(9, 1000, "pkg1", false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt
index 861c6207f5b0..690b9a7248be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapperTest.kt
@@ -25,6 +25,7 @@ import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.time.FakeSystemClock
import org.junit.After
import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -78,4 +79,15 @@ class ControlsFavoritePersistenceWrapperTest : SysuiTestCase() {
assertEquals(list, wrapper.readFavorites())
}
+
+ @Test
+ fun testSaveEmptyOnNonExistingFile() {
+ if (file.exists()) {
+ file.delete()
+ }
+
+ wrapper.storeFavorites(emptyList())
+
+ assertFalse(file.exists())
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
index 3ef60274cd76..c82bb9bbd37c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenBrightnessTest.java
@@ -103,8 +103,6 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
@Test
public void testAod_usesLightSensor() {
- mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
- mScreen.transitionTo(INITIALIZED, DOZE_AOD);
mScreen.onScreenState(Display.STATE_DOZE);
mSensor.sendSensorEvent(3);
@@ -114,8 +112,7 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
@Test
public void testAod_usesDebugValue() throws Exception {
- mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
- mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ mScreen.onScreenState(Display.STATE_DOZE);
Intent intent = new Intent(DozeScreenBrightness.ACTION_AOD_BRIGHTNESS);
intent.putExtra(DozeScreenBrightness.BRIGHTNESS_BUCKET, 1);
@@ -166,14 +163,13 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
}
@Test
- public void testDozingAfterPulsing_pausesLightSensor() throws Exception {
+ public void testScreenOffAfterPulsing_pausesLightSensor() throws Exception {
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE);
mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
mScreen.transitionTo(DOZE_REQUEST_PULSE, DOZE_PULSING);
mScreen.transitionTo(DOZE_PULSING, DOZE_PULSE_DONE);
mScreen.transitionTo(DOZE_PULSE_DONE, DOZE);
- mScreen.onScreenState(Display.STATE_DOZE);
mSensor.sendSensorEvent(1);
@@ -181,6 +177,17 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
}
@Test
+ public void testOnScreenStateSetBeforeTransition_stillRegistersSensor() {
+ mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
+ mScreen.onScreenState(Display.STATE_DOZE);
+ mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+
+ mSensor.sendSensorEvent(1);
+
+ assertEquals(1, mServiceFake.screenBrightness);
+ }
+
+ @Test
public void testNullSensor() throws Exception {
mScreen = new DozeScreenBrightness(mContext, mServiceFake, mSensorManager,
null /* sensor */, mBroadcastDispatcher, mDozeHost, null /* handler */,
@@ -191,12 +198,15 @@ public class DozeScreenBrightnessTest extends SysuiTestCase {
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
mScreen.transitionTo(DOZE_AOD, DOZE_AOD_PAUSING);
mScreen.transitionTo(DOZE_AOD_PAUSING, DOZE_AOD_PAUSED);
+ mScreen.onScreenState(Display.STATE_DOZE);
+ mScreen.onScreenState(Display.STATE_OFF);
}
@Test
public void testNoBrightnessDeliveredAfterFinish() throws Exception {
mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
mScreen.transitionTo(INITIALIZED, DOZE_AOD);
+ mScreen.onScreenState(Display.STATE_DOZE);
mScreen.transitionTo(DOZE_AOD, FINISH);
mSensor.sendSensorEvent(1);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
index ac8c6710e041..5e2e7c075043 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogTest.java
@@ -49,6 +49,7 @@ import android.testing.TestableLooper;
import android.util.FeatureFlagUtils;
import android.view.IWindowManager;
import android.view.View;
+import android.view.WindowManagerPolicyConstants;
import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
@@ -241,6 +242,28 @@ public class GlobalActionsDialogTest extends SysuiTestCase {
verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent.GA_SCREENSHOT_LONG_PRESS);
}
+ @Test
+ public void testShouldShowScreenshot() {
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.integer.config_navBarInteractionMode,
+ WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON);
+
+ GlobalActionsDialog.ScreenshotAction screenshotAction =
+ mGlobalActionsDialog.makeScreenshotActionForTesting();
+ assertThat(screenshotAction.shouldShow()).isTrue();
+ }
+
+ @Test
+ public void testShouldNotShowScreenshot() {
+ mContext.getOrCreateTestableResources().addOverride(
+ com.android.internal.R.integer.config_navBarInteractionMode,
+ WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON);
+
+ GlobalActionsDialog.ScreenshotAction screenshotAction =
+ mGlobalActionsDialog.makeScreenshotActionForTesting();
+ assertThat(screenshotAction.shouldShow()).isFalse();
+ }
+
private void verifyLogPosted(GlobalActionsDialog.GlobalActionsEvent event) {
mTestableLooper.processAllMessages();
verify(mUiEventLogger, times(1))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
index 492b33e3c4a6..609b8474d134 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java
@@ -20,7 +20,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -34,19 +33,23 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
import java.util.ArrayList;
-import java.util.Map;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class MediaDataCombineLatestTest extends SysuiTestCase {
+ @Rule public MockitoRule mockito = MockitoJUnit.rule();
+
private static final String KEY = "TEST_KEY";
private static final String OLD_KEY = "TEST_KEY_OLD";
private static final String APP = "APP";
@@ -59,39 +62,26 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
private MediaDataCombineLatest mManager;
- @Mock private MediaDataManager mDataSource;
- @Mock private MediaDeviceManager mDeviceSource;
@Mock private MediaDataManager.Listener mListener;
- private MediaDataManager.Listener mDataListener;
- private MediaDeviceManager.Listener mDeviceListener;
-
private MediaData mMediaData;
private MediaDeviceData mDeviceData;
@Before
public void setUp() {
- mDataSource = mock(MediaDataManager.class);
- mDeviceSource = mock(MediaDeviceManager.class);
- mListener = mock(MediaDataManager.Listener.class);
-
- mManager = new MediaDataCombineLatest(mDataSource, mDeviceSource);
-
- mDataListener = captureDataListener();
- mDeviceListener = captureDeviceListener();
-
+ mManager = new MediaDataCombineLatest();
mManager.addListener(mListener);
mMediaData = new MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null,
- new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null, false,
- KEY, false);
+ new ArrayList<>(), new ArrayList<>(), PACKAGE, null, null, null, true, null, true,
+ false, KEY, false, false, false);
mDeviceData = new MediaDeviceData(true, null, DEVICE_NAME);
}
@Test
public void eventNotEmittedWithoutDevice() {
// WHEN data source emits an event without device data
- mDataListener.onMediaDataLoaded(KEY, null, mMediaData);
+ mManager.onMediaDataLoaded(KEY, null, mMediaData);
// THEN an event isn't emitted
verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any());
}
@@ -99,7 +89,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
@Test
public void eventNotEmittedWithoutMedia() {
// WHEN device source emits an event without media data
- mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData);
+ mManager.onMediaDeviceChanged(KEY, null, mDeviceData);
// THEN an event isn't emitted
verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any());
}
@@ -107,9 +97,9 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
@Test
public void emitEventAfterDeviceFirst() {
// GIVEN that a device event has already been received
- mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData);
+ mManager.onMediaDeviceChanged(KEY, null, mDeviceData);
// WHEN media event is received
- mDataListener.onMediaDataLoaded(KEY, null, mMediaData);
+ mManager.onMediaDataLoaded(KEY, null, mMediaData);
// THEN the listener receives a combined event
ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class);
verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture());
@@ -119,9 +109,9 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
@Test
public void emitEventAfterMediaFirst() {
// GIVEN that media event has already been received
- mDataListener.onMediaDataLoaded(KEY, null, mMediaData);
+ mManager.onMediaDataLoaded(KEY, null, mMediaData);
// WHEN device event is received
- mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData);
+ mManager.onMediaDeviceChanged(KEY, null, mDeviceData);
// THEN the listener receives a combined event
ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class);
verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture());
@@ -131,11 +121,11 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
@Test
public void migrateKeyMediaFirst() {
// GIVEN that media and device info has already been received
- mDataListener.onMediaDataLoaded(OLD_KEY, null, mMediaData);
- mDeviceListener.onMediaDeviceChanged(OLD_KEY, null, mDeviceData);
+ mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData);
+ mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData);
reset(mListener);
// WHEN a key migration event is received
- mDataListener.onMediaDataLoaded(KEY, OLD_KEY, mMediaData);
+ mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData);
// THEN the listener receives a combined event
ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class);
verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture());
@@ -145,11 +135,11 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
@Test
public void migrateKeyDeviceFirst() {
// GIVEN that media and device info has already been received
- mDataListener.onMediaDataLoaded(OLD_KEY, null, mMediaData);
- mDeviceListener.onMediaDeviceChanged(OLD_KEY, null, mDeviceData);
+ mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData);
+ mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData);
reset(mListener);
// WHEN a key migration event is received
- mDeviceListener.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData);
+ mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData);
// THEN the listener receives a combined event
ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class);
verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture());
@@ -159,12 +149,12 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
@Test
public void migrateKeyMediaAfter() {
// GIVEN that media and device info has already been received
- mDataListener.onMediaDataLoaded(OLD_KEY, null, mMediaData);
- mDeviceListener.onMediaDeviceChanged(OLD_KEY, null, mDeviceData);
- mDeviceListener.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData);
+ mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData);
+ mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData);
+ mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData);
reset(mListener);
// WHEN a second key migration event is received for media
- mDataListener.onMediaDataLoaded(KEY, OLD_KEY, mMediaData);
+ mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData);
// THEN the key has already been migrated
ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class);
verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture());
@@ -174,12 +164,12 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
@Test
public void migrateKeyDeviceAfter() {
// GIVEN that media and device info has already been received
- mDataListener.onMediaDataLoaded(OLD_KEY, null, mMediaData);
- mDeviceListener.onMediaDeviceChanged(OLD_KEY, null, mDeviceData);
- mDataListener.onMediaDataLoaded(KEY, OLD_KEY, mMediaData);
+ mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData);
+ mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData);
+ mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData);
reset(mListener);
// WHEN a second key migration event is received for the device
- mDeviceListener.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData);
+ mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData);
// THEN the key has already be migrated
ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class);
verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture());
@@ -189,60 +179,34 @@ public class MediaDataCombineLatestTest extends SysuiTestCase {
@Test
public void mediaDataRemoved() {
// WHEN media data is removed without first receiving device or data
- mDataListener.onMediaDataRemoved(KEY);
+ mManager.onMediaDataRemoved(KEY);
// THEN a removed event isn't emitted
verify(mListener, never()).onMediaDataRemoved(eq(KEY));
}
@Test
public void mediaDataRemovedAfterMediaEvent() {
- mDataListener.onMediaDataLoaded(KEY, null, mMediaData);
- mDataListener.onMediaDataRemoved(KEY);
+ mManager.onMediaDataLoaded(KEY, null, mMediaData);
+ mManager.onMediaDataRemoved(KEY);
verify(mListener).onMediaDataRemoved(eq(KEY));
}
@Test
public void mediaDataRemovedAfterDeviceEvent() {
- mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData);
- mDataListener.onMediaDataRemoved(KEY);
+ mManager.onMediaDeviceChanged(KEY, null, mDeviceData);
+ mManager.onMediaDataRemoved(KEY);
verify(mListener).onMediaDataRemoved(eq(KEY));
}
@Test
public void mediaDataKeyUpdated() {
// GIVEN that device and media events have already been received
- mDataListener.onMediaDataLoaded(KEY, null, mMediaData);
- mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData);
+ mManager.onMediaDataLoaded(KEY, null, mMediaData);
+ mManager.onMediaDeviceChanged(KEY, null, mDeviceData);
// WHEN the key is changed
- mDataListener.onMediaDataLoaded("NEW_KEY", KEY, mMediaData);
+ mManager.onMediaDataLoaded("NEW_KEY", KEY, mMediaData);
// THEN the listener gets a load event with the correct keys
ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class);
verify(mListener).onMediaDataLoaded(eq("NEW_KEY"), any(), captor.capture());
}
-
- @Test
- public void getDataIncludesDevice() {
- // GIVEN that device and media events have been received
- mDeviceListener.onMediaDeviceChanged(KEY, null, mDeviceData);
- mDataListener.onMediaDataLoaded(KEY, null, mMediaData);
-
- // THEN the result of getData includes device info
- Map<String, MediaData> results = mManager.getData();
- assertThat(results.get(KEY)).isNotNull();
- assertThat(results.get(KEY).getDevice()).isEqualTo(mDeviceData);
- }
-
- private MediaDataManager.Listener captureDataListener() {
- ArgumentCaptor<MediaDataManager.Listener> captor = ArgumentCaptor.forClass(
- MediaDataManager.Listener.class);
- verify(mDataSource).addListener(captor.capture());
- return captor.getValue();
- }
-
- private MediaDeviceManager.Listener captureDeviceListener() {
- ArgumentCaptor<MediaDeviceManager.Listener> captor = ArgumentCaptor.forClass(
- MediaDeviceManager.Listener.class);
- verify(mDeviceSource).addListener(captor.capture());
- return captor.getValue();
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt
index afb64a7649b4..36b6527167f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt
@@ -32,6 +32,7 @@ import org.mockito.Mock
import org.mockito.Mockito
import org.mockito.Mockito.`when`
import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.util.concurrent.Executor
@@ -56,8 +57,6 @@ private fun <T> any(): T = Mockito.any()
class MediaDataFilterTest : SysuiTestCase() {
@Mock
- private lateinit var combineLatest: MediaDataCombineLatest
- @Mock
private lateinit var listener: MediaDataManager.Listener
@Mock
private lateinit var broadcastDispatcher: BroadcastDispatcher
@@ -78,8 +77,9 @@ class MediaDataFilterTest : SysuiTestCase() {
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
- mediaDataFilter = MediaDataFilter(combineLatest, broadcastDispatcher, mediaResumeListener,
- mediaDataManager, lockscreenUserManager, executor)
+ mediaDataFilter = MediaDataFilter(broadcastDispatcher, mediaResumeListener,
+ lockscreenUserManager, executor)
+ mediaDataFilter.mediaDataManager = mediaDataManager
mediaDataFilter.addListener(listener)
// Start all tests as main user
@@ -152,8 +152,9 @@ class MediaDataFilterTest : SysuiTestCase() {
@Test
fun testOnUserSwitched_addsNewUserControls() {
// GIVEN that we had some media for both users
- val dataMap = mapOf(KEY to dataMain, KEY_ALT to dataGuest)
- `when`(combineLatest.getData()).thenReturn(dataMap)
+ mediaDataFilter.onMediaDataLoaded(KEY, null, dataMain)
+ mediaDataFilter.onMediaDataLoaded(KEY_ALT, null, dataGuest)
+ reset(listener)
// and we switch to guest user
setUser(USER_GUEST)
@@ -213,4 +214,4 @@ class MediaDataFilterTest : SysuiTestCase() {
verify(mediaDataManager).setTimedOut(eq(KEY), eq(true))
}
-} \ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
index 568dd6aafc3d..b47ee2921380 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt
@@ -15,6 +15,7 @@ import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.dump.DumpManager
import com.android.systemui.statusbar.SbnBuilder
import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -23,9 +24,13 @@ 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.Mockito
import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.junit.MockitoJUnit
import org.mockito.Mockito.`when` as whenever
@@ -47,6 +52,7 @@ private fun <T> anyObject(): T {
@RunWith(AndroidTestingRunner::class)
class MediaDataManagerTest : SysuiTestCase() {
+ @JvmField @Rule val mockito = MockitoJUnit.rule()
@Mock lateinit var mediaControllerFactory: MediaControllerFactory
@Mock lateinit var controller: MediaController
lateinit var session: MediaSession
@@ -57,19 +63,36 @@ class MediaDataManagerTest : SysuiTestCase() {
@Mock lateinit var broadcastDispatcher: BroadcastDispatcher
@Mock lateinit var mediaTimeoutListener: MediaTimeoutListener
@Mock lateinit var mediaResumeListener: MediaResumeListener
+ @Mock lateinit var mediaSessionBasedFilter: MediaSessionBasedFilter
+ @Mock lateinit var mediaDeviceManager: MediaDeviceManager
+ @Mock lateinit var mediaDataCombineLatest: MediaDataCombineLatest
+ @Mock lateinit var mediaDataFilter: MediaDataFilter
+ @Mock lateinit var listener: MediaDataManager.Listener
@Mock lateinit var pendingIntent: PendingIntent
- @JvmField @Rule val mockito = MockitoJUnit.rule()
lateinit var mediaDataManager: MediaDataManager
lateinit var mediaNotification: StatusBarNotification
+ @Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
@Before
fun setup() {
foregroundExecutor = FakeExecutor(FakeSystemClock())
backgroundExecutor = FakeExecutor(FakeSystemClock())
- mediaDataManager = MediaDataManager(context, backgroundExecutor, foregroundExecutor,
- mediaControllerFactory, broadcastDispatcher, dumpManager,
- mediaTimeoutListener, mediaResumeListener, useMediaResumption = true,
- useQsMediaPlayer = true)
+ mediaDataManager = MediaDataManager(
+ context = context,
+ backgroundExecutor = backgroundExecutor,
+ foregroundExecutor = foregroundExecutor,
+ mediaControllerFactory = mediaControllerFactory,
+ broadcastDispatcher = broadcastDispatcher,
+ dumpManager = dumpManager,
+ mediaTimeoutListener = mediaTimeoutListener,
+ mediaResumeListener = mediaResumeListener,
+ mediaSessionBasedFilter = mediaSessionBasedFilter,
+ mediaDeviceManager = mediaDeviceManager,
+ mediaDataCombineLatest = mediaDataCombineLatest,
+ mediaDataFilter = mediaDataFilter,
+ useMediaResumption = true,
+ useQsMediaPlayer = true
+ )
session = MediaSession(context, "MediaDataManagerTestSession")
mediaNotification = SbnBuilder().run {
setPkg(PACKAGE_NAME)
@@ -84,6 +107,12 @@ class MediaDataManagerTest : SysuiTestCase() {
putString(MediaMetadata.METADATA_KEY_TITLE, SESSION_TITLE)
}
whenever(mediaControllerFactory.create(eq(session.sessionToken))).thenReturn(controller)
+
+ // This is an ugly hack for now. The mediaSessionBasedFilter is one of the internal
+ // listeners in the internal processing pipeline. It receives events, but ince it is a
+ // mock, it doesn't pass those events along the chain to the external listeners. So, just
+ // treat mediaSessionBasedFilter as a listener for testing.
+ listener = mediaSessionBasedFilter
}
@After
@@ -113,8 +142,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnMetaDataLoaded_callsListener() {
- val listener = mock(MediaDataManager.Listener::class.java)
- mediaDataManager.addListener(listener)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java))
verify(listener).onMediaDataLoaded(eq(KEY), eq(null), anyObject())
@@ -122,136 +149,74 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testOnMetaDataLoaded_conservesActiveFlag() {
- val listener = TestListener()
whenever(mediaControllerFactory.create(anyObject())).thenReturn(controller)
whenever(controller.metadata).thenReturn(metadataBuilder.build())
mediaDataManager.addListener(listener)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
- assertThat(listener.data!!.active).isTrue()
+ verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor))
+ assertThat(mediaDataCaptor.value!!.active).isTrue()
}
@Test
fun testOnNotificationRemoved_callsListener() {
- val listener = mock(MediaDataManager.Listener::class.java)
- mediaDataManager.addListener(listener)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java))
mediaDataManager.onNotificationRemoved(KEY)
-
verify(listener).onMediaDataRemoved(eq(KEY))
}
@Test
fun testOnNotificationRemoved_withResumption() {
// GIVEN that the manager has a notification with a resume action
- val listener = TestListener()
- mediaDataManager.addListener(listener)
whenever(controller.metadata).thenReturn(metadataBuilder.build())
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
- val data = listener.data!!
+ verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor))
+ val data = mediaDataCaptor.value
assertThat(data.resumption).isFalse()
mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
// WHEN the notification is removed
mediaDataManager.onNotificationRemoved(KEY)
// THEN the media data indicates that it is for resumption
- assertThat(listener.data!!.resumption).isTrue()
- // AND the new key is the package name
- assertThat(listener.key!!).isEqualTo(PACKAGE_NAME)
- assertThat(listener.oldKey!!).isEqualTo(KEY)
- assertThat(listener.removedKey).isNull()
+ verify(listener).onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor))
+ assertThat(mediaDataCaptor.value.resumption).isTrue()
}
@Test
fun testOnNotificationRemoved_twoWithResumption() {
// GIVEN that the manager has two notifications with resume actions
- val listener = TestListener()
- mediaDataManager.addListener(listener)
whenever(controller.metadata).thenReturn(metadataBuilder.build())
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
mediaDataManager.onNotificationAdded(KEY_2, mediaNotification)
assertThat(backgroundExecutor.runAllReady()).isEqualTo(2)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(2)
- val data = listener.data!!
+ verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor))
+ val data = mediaDataCaptor.value
assertThat(data.resumption).isFalse()
val resumableData = data.copy(resumeAction = Runnable {})
mediaDataManager.onMediaDataLoaded(KEY, null, resumableData)
mediaDataManager.onMediaDataLoaded(KEY_2, null, resumableData)
+ reset(listener)
// WHEN the first is removed
mediaDataManager.onNotificationRemoved(KEY)
// THEN the data is for resumption and the key is migrated to the package name
- assertThat(listener.data!!.resumption).isTrue()
- assertThat(listener.key!!).isEqualTo(PACKAGE_NAME)
- assertThat(listener.oldKey!!).isEqualTo(KEY)
- assertThat(listener.removedKey).isNull()
+ verify(listener).onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor))
+ assertThat(mediaDataCaptor.value.resumption).isTrue()
+ verify(listener, never()).onMediaDataRemoved(eq(KEY))
// WHEN the second is removed
mediaDataManager.onNotificationRemoved(KEY_2)
// THEN the data is for resumption and the second key is removed
- assertThat(listener.data!!.resumption).isTrue()
- assertThat(listener.key!!).isEqualTo(PACKAGE_NAME)
- assertThat(listener.oldKey!!).isEqualTo(PACKAGE_NAME)
- assertThat(listener.removedKey!!).isEqualTo(KEY_2)
- }
-
- @Test
- fun testAppBlockedFromResumption() {
- // GIVEN that the manager has a notification with a resume action
- val listener = TestListener()
- mediaDataManager.addListener(listener)
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
- mediaDataManager.onNotificationAdded(KEY, mediaNotification)
- assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
- assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
- val data = listener.data!!
- assertThat(data.resumption).isFalse()
- mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
-
- // and the manager should block the package from creating resume controls
- val blocked = mutableSetOf(PACKAGE_NAME, "com.example.app")
- mediaDataManager.appsBlockedFromResume = blocked
-
- // WHEN the notification is removed
- mediaDataManager.onNotificationRemoved(KEY)
-
- // THEN the media data is removed
- assertThat(listener.removedKey!!).isEqualTo(KEY)
- }
-
- @Test
- fun testAppUnblockedFromResumption() {
- // GIVEN that an app was blocked from resuming
- val blocked = mutableSetOf(PACKAGE_NAME, "com.example.app")
- mediaDataManager.appsBlockedFromResume = blocked
-
- // and GIVEN that the manager has a notification from that app with a resume action
- val listener = TestListener()
- mediaDataManager.addListener(listener)
- whenever(controller.metadata).thenReturn(metadataBuilder.build())
- mediaDataManager.onNotificationAdded(KEY, mediaNotification)
- assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
- assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
- val data = listener.data!!
- assertThat(data.resumption).isFalse()
- mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {}))
-
- // WHEN the app is unblocked
- mediaDataManager.appsBlockedFromResume = mutableSetOf("com.example.app")
-
- // and the notification is removed
- mediaDataManager.onNotificationRemoved(KEY)
-
- // THEN the entry will stay as a resume control
- assertThat(listener.key!!).isEqualTo(PACKAGE_NAME)
- assertThat(listener.oldKey!!).isEqualTo(KEY)
+ verify(listener).onMediaDataLoaded(eq(PACKAGE_NAME), eq(PACKAGE_NAME),
+ capture(mediaDataCaptor))
+ assertThat(mediaDataCaptor.value.resumption).isTrue()
+ verify(listener).onMediaDataRemoved(eq(KEY_2))
}
@Test
fun testAddResumptionControls() {
- val listener = TestListener()
- mediaDataManager.addListener(listener)
// WHEN resumption controls are added`
val desc = MediaDescription.Builder().run {
setTitle(SESSION_TITLE)
@@ -262,7 +227,8 @@ class MediaDataManagerTest : SysuiTestCase() {
assertThat(backgroundExecutor.runAllReady()).isEqualTo(1)
assertThat(foregroundExecutor.runAllReady()).isEqualTo(1)
// THEN the media data indicates that it is for resumption
- val data = listener.data!!
+ verify(listener).onMediaDataLoaded(eq(PACKAGE_NAME), eq(null), capture(mediaDataCaptor))
+ val data = mediaDataCaptor.value
assertThat(data.resumption).isTrue()
assertThat(data.song).isEqualTo(SESSION_TITLE)
assertThat(data.app).isEqualTo(APP_NAME)
@@ -271,8 +237,6 @@ class MediaDataManagerTest : SysuiTestCase() {
@Test
fun testDismissMedia_listenerCalled() {
- val listener = mock(MediaDataManager.Listener::class.java)
- mediaDataManager.addListener(listener)
mediaDataManager.onNotificationAdded(KEY, mediaNotification)
mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java))
mediaDataManager.dismissMediaData(KEY, 0L)
@@ -282,26 +246,4 @@ class MediaDataManagerTest : SysuiTestCase() {
verify(listener).onMediaDataRemoved(eq(KEY))
}
-
- /**
- * Simple implementation of [MediaDataManager.Listener] for the test.
- *
- * Giving up on trying to get a mock Listener and ArgumentCaptor to work.
- */
- private class TestListener : MediaDataManager.Listener {
- var data: MediaData? = null
- var key: String? = null
- var oldKey: String? = null
- var removedKey: String? = null
-
- override fun onMediaDataLoaded(key: String, oldKey: String?, data: MediaData) {
- this.key = key
- this.oldKey = oldKey
- this.data = data
- }
-
- override fun onMediaDataRemoved(key: String) {
- removedKey = key
- }
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
index 3c6e19f0ec6f..fdb432cc097c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDeviceManagerTest.kt
@@ -68,11 +68,11 @@ private fun <T> eq(value: T): T = Mockito.eq(value) ?: value
public class MediaDeviceManagerTest : SysuiTestCase() {
private lateinit var manager: MediaDeviceManager
- @Mock private lateinit var mediaDataManager: MediaDataManager
@Mock private lateinit var lmmFactory: LocalMediaManagerFactory
@Mock private lateinit var lmm: LocalMediaManager
@Mock private lateinit var mr2: MediaRouter2Manager
- private lateinit var fakeExecutor: FakeExecutor
+ private lateinit var fakeFgExecutor: FakeExecutor
+ private lateinit var fakeBgExecutor: FakeExecutor
@Mock private lateinit var dumpster: DumpManager
@Mock private lateinit var listener: MediaDeviceManager.Listener
@Mock private lateinit var device: MediaDevice
@@ -87,8 +87,9 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
@Before
fun setUp() {
- fakeExecutor = FakeExecutor(FakeSystemClock())
- manager = MediaDeviceManager(context, lmmFactory, mr2, fakeExecutor, mediaDataManager,
+ fakeFgExecutor = FakeExecutor(FakeSystemClock())
+ fakeBgExecutor = FakeExecutor(FakeSystemClock())
+ manager = MediaDeviceManager(context, lmmFactory, mr2, fakeFgExecutor, fakeBgExecutor,
dumpster)
manager.addListener(listener)
@@ -144,13 +145,15 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
fun loadAndRemoveMediaData() {
manager.onMediaDataLoaded(KEY, null, mediaData)
manager.onMediaDataRemoved(KEY)
+ fakeBgExecutor.runAllReady()
verify(lmm).unregisterCallback(any())
}
@Test
fun loadMediaDataWithNullToken() {
manager.onMediaDataLoaded(KEY, null, mediaData.copy(token = null))
- fakeExecutor.runAllReady()
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
val data = captureDeviceData(KEY)
assertThat(data.enabled).isTrue()
assertThat(data.name).isEqualTo(DEVICE_NAME)
@@ -163,6 +166,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
reset(listener)
// WHEN data is loaded with a new key
manager.onMediaDataLoaded(KEY, KEY_OLD, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
// THEN the listener for the old key should removed.
verify(lmm).unregisterCallback(any())
// AND a new device event emitted
@@ -186,6 +191,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
fun unknownOldKey() {
val oldKey = "unknown"
manager.onMediaDataLoaded(KEY, oldKey, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
verify(listener).onMediaDeviceChanged(eq(KEY), eq(oldKey), any())
}
@@ -193,13 +200,16 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
fun updateToSessionTokenWithNullRoute() {
// GIVEN that media data has been loaded with a null token
manager.onMediaDataLoaded(KEY, null, mediaData.copy(token = null))
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
+ reset(listener)
// WHEN media data is loaded with a different token
// AND that token results in a null route
- reset(listener)
whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null)
manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
// THEN the device should be disabled
- fakeExecutor.runAllReady()
val data = captureDeviceData(KEY)
assertThat(data.enabled).isFalse()
assertThat(data.name).isNull()
@@ -210,7 +220,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
fun deviceEventOnAddNotification() {
// WHEN a notification is added
manager.onMediaDataLoaded(KEY, null, mediaData)
- val deviceCallback = captureCallback()
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
// THEN the update is dispatched to the listener
val data = captureDeviceData(KEY)
assertThat(data.enabled).isTrue()
@@ -230,10 +241,12 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
@Test
fun deviceListUpdate() {
manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
val deviceCallback = captureCallback()
// WHEN the device list changes
deviceCallback.onDeviceListUpdate(mutableListOf(device))
- assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
+ assertThat(fakeBgExecutor.runAllReady()).isEqualTo(1)
+ assertThat(fakeFgExecutor.runAllReady()).isEqualTo(1)
// THEN the update is dispatched to the listener
val data = captureDeviceData(KEY)
assertThat(data.enabled).isTrue()
@@ -244,10 +257,12 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
@Test
fun selectedDeviceStateChanged() {
manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
val deviceCallback = captureCallback()
// WHEN the selected device changes state
deviceCallback.onSelectedDeviceStateChanged(device, 1)
- assertThat(fakeExecutor.runAllReady()).isEqualTo(1)
+ assertThat(fakeBgExecutor.runAllReady()).isEqualTo(1)
+ assertThat(fakeFgExecutor.runAllReady()).isEqualTo(1)
// THEN the update is dispatched to the listener
val data = captureDeviceData(KEY)
assertThat(data.enabled).isTrue()
@@ -270,6 +285,8 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null)
// WHEN a notification is added
manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
// THEN the device is disabled
val data = captureDeviceData(KEY)
assertThat(data.enabled).isFalse()
@@ -281,13 +298,16 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
fun deviceDisabledWhenMR2ReturnsNullRouteInfoOnDeviceChanged() {
// GIVEN a notif is added
manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
reset(listener)
// AND MR2Manager returns null for routing session
whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null)
// WHEN the selected device changes state
val deviceCallback = captureCallback()
deviceCallback.onSelectedDeviceStateChanged(device, 1)
- fakeExecutor.runAllReady()
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
// THEN the device is disabled
val data = captureDeviceData(KEY)
assertThat(data.enabled).isFalse()
@@ -299,13 +319,16 @@ public class MediaDeviceManagerTest : SysuiTestCase() {
fun deviceDisabledWhenMR2ReturnsNullRouteInfoOnDeviceListUpdate() {
// GIVEN a notif is added
manager.onMediaDataLoaded(KEY, null, mediaData)
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
reset(listener)
// GIVEN that MR2Manager returns null for routing session
whenever(mr2.getRoutingSessionForMediaController(any())).thenReturn(null)
// WHEN the selected device changes state
val deviceCallback = captureCallback()
deviceCallback.onDeviceListUpdate(mutableListOf(device))
- fakeExecutor.runAllReady()
+ fakeBgExecutor.runAllReady()
+ fakeFgExecutor.runAllReady()
// THEN the device is disabled
val data = captureDeviceData(KEY)
assertThat(data.enabled).isFalse()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
new file mode 100644
index 000000000000..00b003d290ee
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.mock
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+public class MediaPlayerDataTest : SysuiTestCase() {
+
+ companion object {
+ val LOCAL = true
+ val RESUMPTION = true
+ val PLAYING = true
+ val UNDETERMINED = null
+ }
+
+ @Before
+ fun setup() {
+ MediaPlayerData.clear()
+ }
+
+ @Test
+ fun addPlayingThenRemote() {
+ val playerIsPlaying = mock(MediaControlPanel::class.java)
+ val dataIsPlaying = createMediaData("app1", PLAYING, LOCAL, !RESUMPTION)
+
+ val playerIsRemote = mock(MediaControlPanel::class.java)
+ val dataIsRemote = createMediaData("app2", PLAYING, !LOCAL, !RESUMPTION)
+
+ MediaPlayerData.addMediaPlayer("2", dataIsRemote, playerIsRemote)
+ MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying)
+
+ val players = MediaPlayerData.players()
+ assertThat(players).hasSize(2)
+ assertThat(players).containsExactly(playerIsPlaying, playerIsRemote).inOrder()
+ }
+
+ @Test
+ fun switchPlayersPlaying() {
+ val playerIsPlaying1 = mock(MediaControlPanel::class.java)
+ var dataIsPlaying1 = createMediaData("app1", PLAYING, LOCAL, !RESUMPTION)
+
+ val playerIsPlaying2 = mock(MediaControlPanel::class.java)
+ var dataIsPlaying2 = createMediaData("app2", !PLAYING, LOCAL, !RESUMPTION)
+
+ MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1)
+ MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2)
+
+ dataIsPlaying1 = createMediaData("app1", !PLAYING, LOCAL, !RESUMPTION)
+ dataIsPlaying2 = createMediaData("app2", PLAYING, LOCAL, !RESUMPTION)
+
+ MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1)
+ MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2)
+
+ val players = MediaPlayerData.players()
+ assertThat(players).hasSize(2)
+ assertThat(players).containsExactly(playerIsPlaying2, playerIsPlaying1).inOrder()
+ }
+
+ @Test
+ fun fullOrderTest() {
+ val playerIsPlaying = mock(MediaControlPanel::class.java)
+ val dataIsPlaying = createMediaData("app1", PLAYING, LOCAL, !RESUMPTION)
+
+ val playerIsPlayingAndRemote = mock(MediaControlPanel::class.java)
+ val dataIsPlayingAndRemote = createMediaData("app2", PLAYING, !LOCAL, !RESUMPTION)
+
+ val playerIsStoppedAndLocal = mock(MediaControlPanel::class.java)
+ val dataIsStoppedAndLocal = createMediaData("app3", !PLAYING, LOCAL, !RESUMPTION)
+
+ val playerIsStoppedAndRemote = mock(MediaControlPanel::class.java)
+ val dataIsStoppedAndRemote = createMediaData("app4", !PLAYING, !LOCAL, !RESUMPTION)
+
+ val playerCanResume = mock(MediaControlPanel::class.java)
+ val dataCanResume = createMediaData("app5", !PLAYING, LOCAL, RESUMPTION)
+
+ val playerUndetermined = mock(MediaControlPanel::class.java)
+ val dataUndetermined = createMediaData("app6", UNDETERMINED, LOCAL, RESUMPTION)
+
+ MediaPlayerData.addMediaPlayer("3", dataIsStoppedAndLocal, playerIsStoppedAndLocal)
+ MediaPlayerData.addMediaPlayer("5", dataIsStoppedAndRemote, playerIsStoppedAndRemote)
+ MediaPlayerData.addMediaPlayer("4", dataCanResume, playerCanResume)
+ MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying)
+ MediaPlayerData.addMediaPlayer("2", dataIsPlayingAndRemote, playerIsPlayingAndRemote)
+ MediaPlayerData.addMediaPlayer("6", dataUndetermined, playerUndetermined)
+
+ val players = MediaPlayerData.players()
+ assertThat(players).hasSize(6)
+ assertThat(players).containsExactly(playerIsPlaying, playerIsPlayingAndRemote,
+ playerIsStoppedAndLocal, playerCanResume, playerIsStoppedAndRemote,
+ playerUndetermined).inOrder()
+ }
+
+ private fun createMediaData(
+ app: String,
+ isPlaying: Boolean?,
+ isLocalSession: Boolean,
+ resumption: Boolean
+ ) =
+ MediaData(0, false, 0, app, null, null, null, null, emptyList(), emptyList<Int>(), "",
+ null, null, null, true, null, isLocalSession, resumption, null, false, isPlaying)
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt
new file mode 100644
index 000000000000..2d90cc4f6712
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt
@@ -0,0 +1,422 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media
+
+import android.graphics.Color
+import android.media.session.MediaController
+import android.media.session.MediaController.PlaybackInfo
+import android.media.session.MediaSession
+import android.media.session.MediaSessionManager
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.time.FakeSystemClock
+
+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.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.any
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+import org.mockito.Mockito.`when` as whenever
+
+private const val PACKAGE = "PKG"
+private const val KEY = "TEST_KEY"
+private const val NOTIF_KEY = "TEST_KEY"
+private const val SESSION_ARTIST = "SESSION_ARTIST"
+private const val SESSION_TITLE = "SESSION_TITLE"
+private const val APP_NAME = "APP_NAME"
+private const val USER_ID = 0
+
+private val info = MediaData(
+ userId = USER_ID,
+ initialized = true,
+ backgroundColor = Color.DKGRAY,
+ app = APP_NAME,
+ appIcon = null,
+ artist = SESSION_ARTIST,
+ song = SESSION_TITLE,
+ artwork = null,
+ actions = emptyList(),
+ actionsToShowInCompact = emptyList(),
+ packageName = PACKAGE,
+ token = null,
+ clickIntent = null,
+ device = null,
+ active = true,
+ resumeAction = null,
+ resumption = false,
+ notificationKey = NOTIF_KEY,
+ hasCheckedForResume = false
+)
+
+private fun <T> eq(value: T): T = Mockito.eq(value) ?: value
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+public class MediaSessionBasedFilterTest : SysuiTestCase() {
+
+ @JvmField @Rule val mockito = MockitoJUnit.rule()
+
+ // Unit to be tested
+ private lateinit var filter: MediaSessionBasedFilter
+
+ private lateinit var sessionListener: MediaSessionManager.OnActiveSessionsChangedListener
+ @Mock private lateinit var mediaListener: MediaDataManager.Listener
+
+ // MediaSessionBasedFilter dependencies
+ @Mock private lateinit var mediaSessionManager: MediaSessionManager
+ private lateinit var fgExecutor: FakeExecutor
+ private lateinit var bgExecutor: FakeExecutor
+
+ @Mock private lateinit var controller1: MediaController
+ @Mock private lateinit var controller2: MediaController
+ @Mock private lateinit var controller3: MediaController
+ @Mock private lateinit var controller4: MediaController
+
+ private lateinit var token1: MediaSession.Token
+ private lateinit var token2: MediaSession.Token
+ private lateinit var token3: MediaSession.Token
+ private lateinit var token4: MediaSession.Token
+
+ @Mock private lateinit var remotePlaybackInfo: PlaybackInfo
+ @Mock private lateinit var localPlaybackInfo: PlaybackInfo
+
+ private lateinit var session1: MediaSession
+ private lateinit var session2: MediaSession
+ private lateinit var session3: MediaSession
+ private lateinit var session4: MediaSession
+
+ private lateinit var mediaData1: MediaData
+ private lateinit var mediaData2: MediaData
+ private lateinit var mediaData3: MediaData
+ private lateinit var mediaData4: MediaData
+
+ @Before
+ fun setUp() {
+ fgExecutor = FakeExecutor(FakeSystemClock())
+ bgExecutor = FakeExecutor(FakeSystemClock())
+ filter = MediaSessionBasedFilter(context, mediaSessionManager, fgExecutor, bgExecutor)
+
+ // Configure mocks.
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(emptyList())
+
+ session1 = MediaSession(context, "MediaSessionBasedFilter1")
+ session2 = MediaSession(context, "MediaSessionBasedFilter2")
+ session3 = MediaSession(context, "MediaSessionBasedFilter3")
+ session4 = MediaSession(context, "MediaSessionBasedFilter4")
+
+ token1 = session1.sessionToken
+ token2 = session2.sessionToken
+ token3 = session3.sessionToken
+ token4 = session4.sessionToken
+
+ whenever(controller1.getSessionToken()).thenReturn(token1)
+ whenever(controller2.getSessionToken()).thenReturn(token2)
+ whenever(controller3.getSessionToken()).thenReturn(token3)
+ whenever(controller4.getSessionToken()).thenReturn(token4)
+
+ whenever(controller1.getPackageName()).thenReturn(PACKAGE)
+ whenever(controller2.getPackageName()).thenReturn(PACKAGE)
+ whenever(controller3.getPackageName()).thenReturn(PACKAGE)
+ whenever(controller4.getPackageName()).thenReturn(PACKAGE)
+
+ mediaData1 = info.copy(token = token1)
+ mediaData2 = info.copy(token = token2)
+ mediaData3 = info.copy(token = token3)
+ mediaData4 = info.copy(token = token4)
+
+ whenever(remotePlaybackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_REMOTE)
+ whenever(localPlaybackInfo.getPlaybackType()).thenReturn(PlaybackInfo.PLAYBACK_TYPE_LOCAL)
+
+ whenever(controller1.getPlaybackInfo()).thenReturn(localPlaybackInfo)
+ whenever(controller2.getPlaybackInfo()).thenReturn(localPlaybackInfo)
+ whenever(controller3.getPlaybackInfo()).thenReturn(localPlaybackInfo)
+ whenever(controller4.getPlaybackInfo()).thenReturn(localPlaybackInfo)
+
+ // Capture listener
+ bgExecutor.runAllReady()
+ val listenerCaptor = ArgumentCaptor.forClass(
+ MediaSessionManager.OnActiveSessionsChangedListener::class.java)
+ verify(mediaSessionManager).addOnActiveSessionsChangedListener(
+ listenerCaptor.capture(), any())
+ sessionListener = listenerCaptor.value
+
+ filter.addListener(mediaListener)
+ }
+
+ @After
+ fun tearDown() {
+ session1.release()
+ session2.release()
+ session3.release()
+ session4.release()
+ }
+
+ @Test
+ fun noMediaSession_loadedEventNotFiltered() {
+ filter.onMediaDataLoaded(KEY, null, mediaData1)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1))
+ }
+
+ @Test
+ fun noMediaSession_removedEventNotFiltered() {
+ filter.onMediaDataRemoved(KEY)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ verify(mediaListener).onMediaDataRemoved(eq(KEY))
+ }
+
+ @Test
+ fun matchingMediaSession_loadedEventNotFiltered() {
+ // GIVEN an active session
+ val controllers = listOf(controller1)
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers)
+ sessionListener.onActiveSessionsChanged(controllers)
+ // WHEN a loaded event is received that matches the session
+ filter.onMediaDataLoaded(KEY, null, mediaData1)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is not filtered
+ verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1))
+ }
+
+ @Test
+ fun matchingMediaSession_removedEventNotFiltered() {
+ // GIVEN an active session
+ val controllers = listOf(controller1)
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers)
+ sessionListener.onActiveSessionsChanged(controllers)
+ // WHEN a removed event is received
+ filter.onMediaDataRemoved(KEY)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is not filtered
+ verify(mediaListener).onMediaDataRemoved(eq(KEY))
+ }
+
+ @Test
+ fun remoteSession_loadedEventNotFiltered() {
+ // GIVEN a remote session
+ whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo)
+ val controllers = listOf(controller1)
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers)
+ sessionListener.onActiveSessionsChanged(controllers)
+ // WHEN a loaded event is received that matche the session
+ filter.onMediaDataLoaded(KEY, null, mediaData1)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is not filtered
+ verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1))
+ }
+
+ @Test
+ fun remoteAndLocalSessions_localLoadedEventFiltered() {
+ // GIVEN remote and local sessions
+ whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo)
+ val controllers = listOf(controller1, controller2)
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers)
+ sessionListener.onActiveSessionsChanged(controllers)
+ // WHEN a loaded event is received that matches the remote session
+ filter.onMediaDataLoaded(KEY, null, mediaData1)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is not filtered
+ verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1))
+ // WHEN a loaded event is received that matches the local session
+ filter.onMediaDataLoaded(KEY, null, mediaData2)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is filtered
+ verify(mediaListener, never()).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData2))
+ }
+
+ @Test
+ fun remoteAndLocalSessions_remoteSessionWithoutNotification() {
+ // GIVEN remote and local sessions
+ whenever(controller2.getPlaybackInfo()).thenReturn(remotePlaybackInfo)
+ val controllers = listOf(controller1, controller2)
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers)
+ sessionListener.onActiveSessionsChanged(controllers)
+ // WHEN a loaded event is received that matches the local session
+ filter.onMediaDataLoaded(KEY, null, mediaData1)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is not filtered because there isn't a notification for the remote
+ // session.
+ verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1))
+ }
+
+ @Test
+ fun remoteAndLocalHaveDifferentKeys_localLoadedEventFiltered() {
+ // GIVEN remote and local sessions
+ val key1 = "KEY_1"
+ val key2 = "KEY_2"
+ whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo)
+ val controllers = listOf(controller1, controller2)
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers)
+ sessionListener.onActiveSessionsChanged(controllers)
+ // WHEN a loaded event is received that matches the remote session
+ filter.onMediaDataLoaded(key1, null, mediaData1)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is not filtered
+ verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1))
+ // WHEN a loaded event is received that matches the local session
+ filter.onMediaDataLoaded(key2, null, mediaData2)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is filtered
+ verify(mediaListener, never()).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2))
+ // AND there should be a removed event for key2
+ verify(mediaListener).onMediaDataRemoved(eq(key2))
+ }
+
+ @Test
+ fun remoteAndLocalHaveDifferentKeys_remoteSessionWithoutNotification() {
+ // GIVEN remote and local sessions
+ val key1 = "KEY_1"
+ val key2 = "KEY_2"
+ whenever(controller2.getPlaybackInfo()).thenReturn(remotePlaybackInfo)
+ val controllers = listOf(controller1, controller2)
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers)
+ sessionListener.onActiveSessionsChanged(controllers)
+ // WHEN a loaded event is received that matches the local session
+ filter.onMediaDataLoaded(key1, null, mediaData1)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is not filtered
+ verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1))
+ // WHEN a loaded event is received that matches the remote session
+ filter.onMediaDataLoaded(key2, null, mediaData2)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is not filtered
+ verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2))
+ }
+
+ @Test
+ fun multipleRemoteSessions_loadedEventNotFiltered() {
+ // GIVEN two remote sessions
+ whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo)
+ whenever(controller2.getPlaybackInfo()).thenReturn(remotePlaybackInfo)
+ val controllers = listOf(controller1, controller2)
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers)
+ sessionListener.onActiveSessionsChanged(controllers)
+ // WHEN a loaded event is received that matches the remote session
+ filter.onMediaDataLoaded(KEY, null, mediaData1)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is not filtered
+ verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1))
+ // WHEN a loaded event is received that matches the local session
+ filter.onMediaDataLoaded(KEY, null, mediaData2)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is not filtered
+ verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData2))
+ }
+
+ @Test
+ fun multipleOtherSessions_loadedEventNotFiltered() {
+ // GIVEN multiple active sessions from other packages
+ val controllers = listOf(controller1, controller2, controller3, controller4)
+ whenever(controller1.getPackageName()).thenReturn("PKG_1")
+ whenever(controller2.getPackageName()).thenReturn("PKG_2")
+ whenever(controller3.getPackageName()).thenReturn("PKG_3")
+ whenever(controller4.getPackageName()).thenReturn("PKG_4")
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers)
+ sessionListener.onActiveSessionsChanged(controllers)
+ // WHEN a loaded event is received
+ filter.onMediaDataLoaded(KEY, null, mediaData1)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the event is not filtered
+ verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1))
+ }
+
+ @Test
+ fun doNotFilterDuringKeyMigration() {
+ val key1 = "KEY_1"
+ val key2 = "KEY_2"
+ // GIVEN a loaded event
+ filter.onMediaDataLoaded(key1, null, mediaData2)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ reset(mediaListener)
+ // GIVEN remote and local sessions
+ whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo)
+ val controllers = listOf(controller1, controller2)
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers)
+ sessionListener.onActiveSessionsChanged(controllers)
+ // WHEN a loaded event is received that matches the local session but it is a key migration
+ filter.onMediaDataLoaded(key2, key1, mediaData2)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the key migration event is fired
+ verify(mediaListener).onMediaDataLoaded(eq(key2), eq(key1), eq(mediaData2))
+ }
+
+ @Test
+ fun filterAfterKeyMigration() {
+ val key1 = "KEY_1"
+ val key2 = "KEY_2"
+ // GIVEN a loaded event
+ filter.onMediaDataLoaded(key1, null, mediaData1)
+ filter.onMediaDataLoaded(key1, null, mediaData2)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ reset(mediaListener)
+ // GIVEN remote and local sessions
+ whenever(controller1.getPlaybackInfo()).thenReturn(remotePlaybackInfo)
+ val controllers = listOf(controller1, controller2)
+ whenever(mediaSessionManager.getActiveSessions(any())).thenReturn(controllers)
+ sessionListener.onActiveSessionsChanged(controllers)
+ // GIVEN that the keys have been migrated
+ filter.onMediaDataLoaded(key2, key1, mediaData1)
+ filter.onMediaDataLoaded(key2, key1, mediaData2)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ reset(mediaListener)
+ // WHEN a loaded event is received that matches the local session
+ filter.onMediaDataLoaded(key2, null, mediaData2)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the key migration event is filtered
+ verify(mediaListener, never()).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2))
+ // WHEN a loaded event is received that matches the remote session
+ filter.onMediaDataLoaded(key2, null, mediaData1)
+ bgExecutor.runAllReady()
+ fgExecutor.runAllReady()
+ // THEN the key migration event is fired
+ verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData1))
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
index e98b6b69ee76..4c9e141c45cc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingServiceTest.java
@@ -32,7 +32,9 @@ import androidx.test.filters.SmallTest;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.settings.CurrentUserContextTracker;
+import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
import org.junit.Before;
import org.junit.Test;
@@ -61,6 +63,12 @@ public class RecordingServiceTest extends SysuiTestCase {
private Executor mExecutor;
@Mock
private CurrentUserContextTracker mUserContextTracker;
+ private KeyguardDismissUtil mKeyguardDismissUtil = new KeyguardDismissUtil() {
+ public void executeWhenUnlocked(ActivityStarter.OnDismissAction action,
+ boolean requiresShadeOpen) {
+ action.onDismiss();
+ }
+ };
private RecordingService mRecordingService;
@@ -68,7 +76,7 @@ public class RecordingServiceTest extends SysuiTestCase {
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
mRecordingService = Mockito.spy(new RecordingService(mController, mExecutor, mUiEventLogger,
- mNotificationManager, mUserContextTracker));
+ mNotificationManager, mUserContextTracker, mKeyguardDismissUtil));
// Return actual context info
doReturn(mContext).when(mRecordingService).getApplicationContext();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 80fa8cc7d931..92a2c8738344 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -211,6 +211,19 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase {
}
@Test
+ public void testUpdateNotificationViews_appOps() throws Exception {
+ NotificationEntry entry0 = createEntry();
+ entry0.setRow(spy(entry0.getRow()));
+ when(mEntryManager.getVisibleNotifications()).thenReturn(
+ Lists.newArrayList(entry0));
+ mListContainer.addContainerView(entry0.getRow());
+
+ mViewHierarchyManager.updateNotificationViews();
+
+ verify(entry0.getRow(), times(1)).showAppOpsIcons(any());
+ }
+
+ @Test
public void testReentrantCallsToOnDynamicPrivacyChangedPostForLater() {
// GIVEN a ListContainer that will make a re-entrant call to updateNotificationViews()
mMadeReentrantCall = false;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
index ae39035e8666..314b19140e7a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
@@ -72,6 +72,8 @@ public class AppOpsCoordinatorTest extends SysuiTestCase {
private Notification mNotification;
private AppOpsCoordinator mAppOpsCoordinator;
private NotifFilter mForegroundFilter;
+ private NotifCollectionListener mNotifCollectionListener;
+ private AppOpsController.Callback mAppOpsCallback;
private NotifLifetimeExtender mForegroundNotifLifetimeExtender;
private FakeSystemClock mClock = new FakeSystemClock();
@@ -108,6 +110,18 @@ public class AppOpsCoordinatorTest extends SysuiTestCase {
lifetimeExtenderCaptor.capture());
mForegroundNotifLifetimeExtender = lifetimeExtenderCaptor.getValue();
+ // capture notifCollectionListener
+ ArgumentCaptor<NotifCollectionListener> notifCollectionCaptor =
+ ArgumentCaptor.forClass(NotifCollectionListener.class);
+ verify(mNotifPipeline, times(1)).addCollectionListener(
+ notifCollectionCaptor.capture());
+ mNotifCollectionListener = notifCollectionCaptor.getValue();
+
+ // capture app ops callback
+ ArgumentCaptor<AppOpsController.Callback> appOpsCaptor =
+ ArgumentCaptor.forClass(AppOpsController.Callback.class);
+ verify(mAppOpsController).addCallback(any(int[].class), appOpsCaptor.capture());
+ mAppOpsCallback = appOpsCaptor.getValue();
}
@Test
@@ -201,4 +215,134 @@ public class AppOpsCoordinatorTest extends SysuiTestCase {
assertFalse(mForegroundNotifLifetimeExtender
.shouldExtendLifetime(mEntry, NotificationListenerService.REASON_CLICK));
}
+
+ @Test
+ public void testAppOpsUpdateOnlyAppliedToRelevantNotificationWithStandardLayout() {
+ // GIVEN three current notifications, two with the same key but from different users
+ NotificationEntry entry1 = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .setPkg(TEST_PKG)
+ .setId(1)
+ .build();
+ NotificationEntry entry2 = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .setPkg(TEST_PKG)
+ .setId(2)
+ .build();
+ NotificationEntry entry3_diffUser = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID + 1))
+ .setPkg(TEST_PKG)
+ .setId(2)
+ .build();
+ when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry1, entry2, entry3_diffUser));
+
+ // GIVEN that only entry2 has a standard layout
+ when(mForegroundServiceController.getStandardLayoutKeys(NOTIF_USER_ID, TEST_PKG))
+ .thenReturn(new ArraySet<>(List.of(entry2.getKey())));
+
+ // WHEN a new app ops code comes in
+ mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true);
+ mExecutor.runAllReady();
+
+ // THEN entry2's app ops are updated, but no one else's are
+ assertEquals(
+ new ArraySet<>(),
+ entry1.mActiveAppOps);
+ assertEquals(
+ new ArraySet<>(List.of(47)),
+ entry2.mActiveAppOps);
+ assertEquals(
+ new ArraySet<>(),
+ entry3_diffUser.mActiveAppOps);
+ }
+
+ @Test
+ public void testAppOpsUpdateAppliedToAllNotificationsWithStandardLayouts() {
+ // GIVEN three notifications with standard layouts
+ NotificationEntry entry1 = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .setPkg(TEST_PKG)
+ .setId(1)
+ .build();
+ NotificationEntry entry2 = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .setPkg(TEST_PKG)
+ .setId(2)
+ .build();
+ NotificationEntry entry3 = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .setPkg(TEST_PKG)
+ .setId(3)
+ .build();
+ when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry1, entry2, entry3));
+ when(mForegroundServiceController.getStandardLayoutKeys(NOTIF_USER_ID, TEST_PKG))
+ .thenReturn(new ArraySet<>(List.of(entry1.getKey(), entry2.getKey(),
+ entry3.getKey())));
+
+ // WHEN a new app ops code comes in
+ mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true);
+ mExecutor.runAllReady();
+
+ // THEN all entries get updated
+ assertEquals(
+ new ArraySet<>(List.of(47)),
+ entry1.mActiveAppOps);
+ assertEquals(
+ new ArraySet<>(List.of(47)),
+ entry2.mActiveAppOps);
+ assertEquals(
+ new ArraySet<>(List.of(47)),
+ entry3.mActiveAppOps);
+ }
+
+ @Test
+ public void testAppOpsAreRemoved() {
+ // GIVEN One notification which is associated with app ops
+ NotificationEntry entry = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .setPkg(TEST_PKG)
+ .setId(2)
+ .build();
+ when(mNotifPipeline.getAllNotifs()).thenReturn(List.of(entry));
+ when(mForegroundServiceController.getStandardLayoutKeys(0, TEST_PKG))
+ .thenReturn(new ArraySet<>(List.of(entry.getKey())));
+
+ // GIVEN that the notification's app ops are already [47, 33]
+ mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, true);
+ mAppOpsCallback.onActiveStateChanged(33, NOTIF_USER_ID, TEST_PKG, true);
+ mExecutor.runAllReady();
+ assertEquals(
+ new ArraySet<>(List.of(47, 33)),
+ entry.mActiveAppOps);
+
+ // WHEN one of the app ops is removed
+ mAppOpsCallback.onActiveStateChanged(47, NOTIF_USER_ID, TEST_PKG, false);
+ mExecutor.runAllReady();
+
+ // THEN the entry's active app ops are updated as well
+ assertEquals(
+ new ArraySet<>(List.of(33)),
+ entry.mActiveAppOps);
+ }
+
+ @Test
+ public void testNullAppOps() {
+ // GIVEN one notification with app ops
+ NotificationEntry entry = new NotificationEntryBuilder()
+ .setUser(new UserHandle(NOTIF_USER_ID))
+ .setPkg(TEST_PKG)
+ .setId(2)
+ .build();
+ entry.mActiveAppOps.clear();
+ entry.mActiveAppOps.addAll(List.of(47, 33));
+
+ // WHEN the notification is updated and the foreground service controller returns null for
+ // this notification
+ when(mForegroundServiceController.getAppOps(entry.getSbn().getUser().getIdentifier(),
+ entry.getSbn().getPackageName())).thenReturn(null);
+ mNotifCollectionListener.onEntryUpdated(entry);
+
+ // THEN the entry's active app ops is updated to empty
+ assertTrue(entry.mActiveAppOps.isEmpty());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java
new file mode 100644
index 000000000000..43d8b50bcf72
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/AppOpsInfoTest.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2018 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.notification.row;
+
+import static android.app.AppOpsManager.OP_CAMERA;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.UiThreadTest;
+import android.util.ArraySet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.logging.testing.UiEventLoggerFake;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.CountDownLatch;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@UiThreadTest
+public class AppOpsInfoTest extends SysuiTestCase {
+ private static final String TEST_PACKAGE_NAME = "test_package";
+ private static final int TEST_UID = 1;
+
+ private AppOpsInfo mAppOpsInfo;
+ private final PackageManager mMockPackageManager = mock(PackageManager.class);
+ private final NotificationGuts mGutsParent = mock(NotificationGuts.class);
+ private StatusBarNotification mSbn;
+ private UiEventLoggerFake mUiEventLogger = new UiEventLoggerFake();
+
+ @Before
+ public void setUp() throws Exception {
+ // Inflate the layout
+ final LayoutInflater layoutInflater = LayoutInflater.from(mContext);
+ mAppOpsInfo = (AppOpsInfo) layoutInflater.inflate(R.layout.app_ops_info, null);
+ mAppOpsInfo.setGutsParent(mGutsParent);
+
+ // PackageManager must return a packageInfo and applicationInfo.
+ final PackageInfo packageInfo = new PackageInfo();
+ packageInfo.packageName = TEST_PACKAGE_NAME;
+ when(mMockPackageManager.getPackageInfo(eq(TEST_PACKAGE_NAME), anyInt()))
+ .thenReturn(packageInfo);
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.uid = TEST_UID; // non-zero
+ when(mMockPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(
+ applicationInfo);
+
+ mSbn = new StatusBarNotification(TEST_PACKAGE_NAME, TEST_PACKAGE_NAME, 0, null, TEST_UID, 0,
+ new Notification(), UserHandle.CURRENT, null, 0);
+ }
+
+ @Test
+ public void testBindNotification_SetsTextApplicationName() {
+ when(mMockPackageManager.getApplicationLabel(any())).thenReturn("App Name");
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>());
+ final TextView textView = mAppOpsInfo.findViewById(R.id.pkgname);
+ assertTrue(textView.getText().toString().contains("App Name"));
+ }
+
+ @Test
+ public void testBindNotification_SetsPackageIcon() {
+ final Drawable iconDrawable = mock(Drawable.class);
+ when(mMockPackageManager.getApplicationIcon(any(ApplicationInfo.class)))
+ .thenReturn(iconDrawable);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>());
+ final ImageView iconView = mAppOpsInfo.findViewById(R.id.pkgicon);
+ assertEquals(iconDrawable, iconView.getDrawable());
+ }
+
+ @Test
+ public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ final CountDownLatch latch = new CountDownLatch(1);
+ mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid,
+ ArraySet<Integer> ops) -> {
+ assertEquals(TEST_PACKAGE_NAME, pkg);
+ assertEquals(expectedOps, ops);
+ assertEquals(TEST_UID, uid);
+ latch.countDown();
+ }, mSbn, mUiEventLogger, expectedOps);
+
+ final View settingsButton = mAppOpsInfo.findViewById(R.id.settings);
+ settingsButton.performClick();
+ // Verify that listener was triggered.
+ assertEquals(0, latch.getCount());
+ }
+
+ @Test
+ public void testBindNotification_LogsOpen() throws Exception {
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, new ArraySet<>());
+ assertEquals(1, mUiEventLogger.numLogs());
+ assertEquals(NotificationAppOpsEvent.NOTIFICATION_APP_OPS_OPEN.getId(),
+ mUiEventLogger.eventId(0));
+ }
+
+ @Test
+ public void testOk() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ final CountDownLatch latch = new CountDownLatch(1);
+ mAppOpsInfo.bindGuts(mMockPackageManager, (View v, String pkg, int uid,
+ ArraySet<Integer> ops) -> {
+ assertEquals(TEST_PACKAGE_NAME, pkg);
+ assertEquals(expectedOps, ops);
+ assertEquals(TEST_UID, uid);
+ latch.countDown();
+ }, mSbn, mUiEventLogger, expectedOps);
+
+ final View okButton = mAppOpsInfo.findViewById(R.id.ok);
+ okButton.performClick();
+ assertEquals(1, latch.getCount());
+ verify(mGutsParent, times(1)).closeControls(eq(okButton), anyBoolean());
+ }
+
+ @Test
+ public void testPrompt_camera() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is using the camera.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_mic() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_RECORD_AUDIO);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is using the microphone.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_overlay() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is displaying over other apps on your screen.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_camera_mic() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ expectedOps.add(OP_RECORD_AUDIO);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is using the microphone and camera.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_camera_mic_overlay() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ expectedOps.add(OP_RECORD_AUDIO);
+ expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is displaying over other apps on your screen and using"
+ + " the microphone and camera.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_camera_overlay() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_CAMERA);
+ expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is displaying over other apps on your screen and using"
+ + " the camera.", prompt.getText());
+ }
+
+ @Test
+ public void testPrompt_mic_overlay() {
+ ArraySet<Integer> expectedOps = new ArraySet<>();
+ expectedOps.add(OP_RECORD_AUDIO);
+ expectedOps.add(OP_SYSTEM_ALERT_WINDOW);
+ mAppOpsInfo.bindGuts(mMockPackageManager, null, mSbn, mUiEventLogger, expectedOps);
+ TextView prompt = mAppOpsInfo.findViewById(R.id.prompt);
+ assertEquals("This app is displaying over other apps on your screen and using"
+ + " the microphone.", prompt.getText());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index 4758d2318889..2684cc29aa93 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -35,10 +35,12 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.app.AppOpsManager;
import android.app.NotificationChannel;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
+import android.util.ArraySet;
import android.view.View;
import androidx.test.filters.SmallTest;
@@ -211,6 +213,46 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
}
@Test
+ public void testShowAppOps_noHeader() {
+ // public notification is custom layout - no header
+ mGroupRow.setSensitive(true, true);
+ mGroupRow.setAppOpsOnClickListener(null);
+ mGroupRow.showAppOpsIcons(null);
+ }
+
+ @Test
+ public void testShowAppOpsIcons_header() {
+ NotificationContentView publicLayout = mock(NotificationContentView.class);
+ mGroupRow.setPublicLayout(publicLayout);
+ NotificationContentView privateLayout = mock(NotificationContentView.class);
+ mGroupRow.setPrivateLayout(privateLayout);
+ NotificationChildrenContainer mockContainer = mock(NotificationChildrenContainer.class);
+ when(mockContainer.getNotificationChildCount()).thenReturn(1);
+ mGroupRow.setChildrenContainer(mockContainer);
+
+ ArraySet<Integer> ops = new ArraySet<>();
+ ops.add(AppOpsManager.OP_ANSWER_PHONE_CALLS);
+ mGroupRow.showAppOpsIcons(ops);
+
+ verify(mockContainer, times(1)).showAppOpsIcons(ops);
+ verify(privateLayout, times(1)).showAppOpsIcons(ops);
+ verify(publicLayout, times(1)).showAppOpsIcons(ops);
+
+ }
+
+ @Test
+ public void testAppOpsOnClick() {
+ ExpandableNotificationRow.OnAppOpsClickListener l = mock(
+ ExpandableNotificationRow.OnAppOpsClickListener.class);
+ View view = mock(View.class);
+
+ mGroupRow.setAppOpsOnClickListener(l);
+
+ mGroupRow.getAppOpsOnClickListener().onClick(view);
+ verify(l, times(1)).onClick(any(), anyInt(), anyInt(), any());
+ }
+
+ @Test
public void testHeadsUpAnimatingAwayListener() {
mGroupRow.setHeadsUpAnimatingAway(true);
Assert.assertEquals(true, mHeadsUpAnimatingAway);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
index b02f2746ce7a..ed4f8b330e23 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java
@@ -76,6 +76,32 @@ public class NotificationContentViewTest extends SysuiTestCase {
@Test
@UiThreadTest
+ public void testShowAppOpsIcons() {
+ View mockContracted = mock(NotificationHeaderView.class);
+ when(mockContracted.findViewById(com.android.internal.R.id.mic))
+ .thenReturn(mockContracted);
+ View mockExpanded = mock(NotificationHeaderView.class);
+ when(mockExpanded.findViewById(com.android.internal.R.id.mic))
+ .thenReturn(mockExpanded);
+ View mockHeadsUp = mock(NotificationHeaderView.class);
+ when(mockHeadsUp.findViewById(com.android.internal.R.id.mic))
+ .thenReturn(mockHeadsUp);
+
+ mView.setContractedChild(mockContracted);
+ mView.setExpandedChild(mockExpanded);
+ mView.setHeadsUpChild(mockHeadsUp);
+
+ ArraySet<Integer> ops = new ArraySet<>();
+ ops.add(AppOpsManager.OP_RECORD_AUDIO);
+ mView.showAppOpsIcons(ops);
+
+ verify(mockContracted, times(1)).setVisibility(View.VISIBLE);
+ verify(mockExpanded, times(1)).setVisibility(View.VISIBLE);
+ verify(mockHeadsUp, times(1)).setVisibility(View.VISIBLE);
+ }
+
+ @Test
+ @UiThreadTest
public void testExpandButtonFocusIsCalled() {
View mockContractedEB = mock(NotificationExpandButton.class);
View mockContracted = mock(NotificationHeaderView.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index d2ff2ad8a684..0c6409b38d21 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -421,6 +421,7 @@ public class NotificationTestHelper {
mBindStage,
mock(OnExpandClickListener.class),
mock(NotificationMediaManager.class),
+ mock(ExpandableNotificationRow.OnAppOpsClickListener.class),
mock(FalsingManager.class),
mStatusBarStateController,
mPeopleNotificationIdentifier);
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java
index 1c4db1214d3b..59ba82e4616a 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionManagerService.java
@@ -34,6 +34,7 @@ import android.app.prediction.IPredictionManager;
import android.content.Context;
import android.content.pm.ParceledListSlice;
import android.os.Binder;
+import android.os.IBinder;
import android.os.ResultReceiver;
import android.os.ShellCallback;
import android.util.Slog;
@@ -108,9 +109,9 @@ public class AppPredictionManagerService extends
@Override
public void createPredictionSession(@NonNull AppPredictionContext context,
- @NonNull AppPredictionSessionId sessionId) {
- runForUserLocked("createPredictionSession", sessionId,
- (service) -> service.onCreatePredictionSessionLocked(context, sessionId));
+ @NonNull AppPredictionSessionId sessionId, @NonNull IBinder token) {
+ runForUserLocked("createPredictionSession", sessionId, (service) ->
+ service.onCreatePredictionSessionLocked(context, sessionId, token));
}
@Override
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index 103151dcdda5..f9cd60a43524 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -30,6 +30,7 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice;
import android.content.pm.ServiceInfo;
+import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.provider.DeviceConfig;
@@ -44,8 +45,6 @@ import com.android.server.LocalServices;
import com.android.server.infra.AbstractPerUserSystemService;
import com.android.server.people.PeopleServiceInternal;
-import java.util.function.Consumer;
-
/**
* Per-user instance of {@link AppPredictionManagerService}.
*/
@@ -112,17 +111,24 @@ public class AppPredictionPerUserService extends
*/
@GuardedBy("mLock")
public void onCreatePredictionSessionLocked(@NonNull AppPredictionContext context,
- @NonNull AppPredictionSessionId sessionId) {
- if (!mSessionInfos.containsKey(sessionId)) {
- mSessionInfos.put(sessionId, new AppPredictionSessionInfo(sessionId, context,
- DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
- PREDICT_USING_PEOPLE_SERVICE_PREFIX + context.getUiSurface(), false),
- this::removeAppPredictionSessionInfo));
- }
- final boolean serviceExists = resolveService(sessionId, s ->
- s.onCreatePredictionSession(context, sessionId), true);
- if (!serviceExists) {
- mSessionInfos.remove(sessionId);
+ @NonNull AppPredictionSessionId sessionId, @NonNull IBinder token) {
+ final boolean usesPeopleService = DeviceConfig.getBoolean(NAMESPACE_SYSTEMUI,
+ PREDICT_USING_PEOPLE_SERVICE_PREFIX + context.getUiSurface(), false);
+ final boolean serviceExists = resolveService(sessionId, false,
+ usesPeopleService, s -> s.onCreatePredictionSession(context, sessionId));
+ if (serviceExists && !mSessionInfos.containsKey(sessionId)) {
+ final AppPredictionSessionInfo sessionInfo = new AppPredictionSessionInfo(
+ sessionId, context, usesPeopleService, token, () -> {
+ synchronized (mLock) {
+ onDestroyPredictionSessionLocked(sessionId);
+ }
+ });
+ if (sessionInfo.linkToDeath()) {
+ mSessionInfos.put(sessionId, sessionInfo);
+ } else {
+ // destroy the session if calling process is already dead
+ onDestroyPredictionSessionLocked(sessionId);
+ }
}
}
@@ -132,7 +138,10 @@ public class AppPredictionPerUserService extends
@GuardedBy("mLock")
public void notifyAppTargetEventLocked(@NonNull AppPredictionSessionId sessionId,
@NonNull AppTargetEvent event) {
- resolveService(sessionId, s -> s.notifyAppTargetEvent(sessionId, event), false);
+ final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+ if (sessionInfo == null) return;
+ resolveService(sessionId, false, sessionInfo.mUsesPeopleService,
+ s -> s.notifyAppTargetEvent(sessionId, event));
}
/**
@@ -141,8 +150,10 @@ public class AppPredictionPerUserService extends
@GuardedBy("mLock")
public void notifyLaunchLocationShownLocked(@NonNull AppPredictionSessionId sessionId,
@NonNull String launchLocation, @NonNull ParceledListSlice targetIds) {
- resolveService(sessionId, s ->
- s.notifyLaunchLocationShown(sessionId, launchLocation, targetIds), false);
+ final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+ if (sessionInfo == null) return;
+ resolveService(sessionId, false, sessionInfo.mUsesPeopleService,
+ s -> s.notifyLaunchLocationShown(sessionId, launchLocation, targetIds));
}
/**
@@ -151,7 +162,10 @@ public class AppPredictionPerUserService extends
@GuardedBy("mLock")
public void sortAppTargetsLocked(@NonNull AppPredictionSessionId sessionId,
@NonNull ParceledListSlice targets, @NonNull IPredictionCallback callback) {
- resolveService(sessionId, s -> s.sortAppTargets(sessionId, targets, callback), true);
+ final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+ if (sessionInfo == null) return;
+ resolveService(sessionId, true, sessionInfo.mUsesPeopleService,
+ s -> s.sortAppTargets(sessionId, targets, callback));
}
/**
@@ -160,10 +174,12 @@ public class AppPredictionPerUserService extends
@GuardedBy("mLock")
public void registerPredictionUpdatesLocked(@NonNull AppPredictionSessionId sessionId,
@NonNull IPredictionCallback callback) {
- final boolean serviceExists = resolveService(sessionId, s ->
- s.registerPredictionUpdates(sessionId, callback), false);
final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
- if (serviceExists && sessionInfo != null) {
+ if (sessionInfo == null) return;
+ final boolean serviceExists = resolveService(sessionId, false,
+ sessionInfo.mUsesPeopleService,
+ s -> s.registerPredictionUpdates(sessionId, callback));
+ if (serviceExists) {
sessionInfo.addCallbackLocked(callback);
}
}
@@ -174,10 +190,12 @@ public class AppPredictionPerUserService extends
@GuardedBy("mLock")
public void unregisterPredictionUpdatesLocked(@NonNull AppPredictionSessionId sessionId,
@NonNull IPredictionCallback callback) {
- final boolean serviceExists = resolveService(sessionId, s ->
- s.unregisterPredictionUpdates(sessionId, callback), false);
final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
- if (serviceExists && sessionInfo != null) {
+ if (sessionInfo == null) return;
+ final boolean serviceExists = resolveService(sessionId, false,
+ sessionInfo.mUsesPeopleService,
+ s -> s.unregisterPredictionUpdates(sessionId, callback));
+ if (serviceExists) {
sessionInfo.removeCallbackLocked(callback);
}
}
@@ -187,7 +205,10 @@ public class AppPredictionPerUserService extends
*/
@GuardedBy("mLock")
public void requestPredictionUpdateLocked(@NonNull AppPredictionSessionId sessionId) {
- resolveService(sessionId, s -> s.requestPredictionUpdate(sessionId), true);
+ final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+ if (sessionInfo == null) return;
+ resolveService(sessionId, true, sessionInfo.mUsesPeopleService,
+ s -> s.requestPredictionUpdate(sessionId));
}
/**
@@ -195,12 +216,14 @@ public class AppPredictionPerUserService extends
*/
@GuardedBy("mLock")
public void onDestroyPredictionSessionLocked(@NonNull AppPredictionSessionId sessionId) {
- final boolean serviceExists = resolveService(sessionId, s ->
- s.onDestroyPredictionSession(sessionId), false);
- final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
- if (serviceExists && sessionInfo != null) {
- sessionInfo.destroy();
+ if (isDebug()) {
+ Slog.d(TAG, "onDestroyPredictionSessionLocked(): sessionId=" + sessionId);
}
+ final AppPredictionSessionInfo sessionInfo = mSessionInfos.remove(sessionId);
+ if (sessionInfo == null) return;
+ resolveService(sessionId, false, sessionInfo.mUsesPeopleService,
+ s -> s.onDestroyPredictionSession(sessionId));
+ sessionInfo.destroy();
}
@Override
@@ -291,27 +314,18 @@ public class AppPredictionPerUserService extends
}
for (AppPredictionSessionInfo sessionInfo : mSessionInfos.values()) {
- sessionInfo.resurrectSessionLocked(this);
- }
- }
-
- private void removeAppPredictionSessionInfo(AppPredictionSessionId sessionId) {
- if (isDebug()) {
- Slog.d(TAG, "removeAppPredictionSessionInfo(): sessionId=" + sessionId);
- }
- synchronized (mLock) {
- mSessionInfos.remove(sessionId);
+ sessionInfo.resurrectSessionLocked(this, sessionInfo.mToken);
}
}
@GuardedBy("mLock")
@Nullable
- protected boolean resolveService(@NonNull final AppPredictionSessionId sessionId,
- @NonNull final AbstractRemoteService.AsyncRequest<IPredictionService> cb,
- boolean sendImmediately) {
- final AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
- if (sessionInfo == null) return false;
- if (sessionInfo.mUsesPeopleService) {
+ protected boolean resolveService(
+ @NonNull final AppPredictionSessionId sessionId,
+ boolean sendImmediately,
+ boolean usesPeopleService,
+ @NonNull final AbstractRemoteService.AsyncRequest<IPredictionService> cb) {
+ if (usesPeopleService) {
final IPredictionService service =
LocalServices.getService(PeopleServiceInternal.class);
if (service != null) {
@@ -368,7 +382,9 @@ public class AppPredictionPerUserService extends
private final AppPredictionContext mPredictionContext;
private final boolean mUsesPeopleService;
@NonNull
- private final Consumer<AppPredictionSessionId> mRemoveSessionInfoAction;
+ final IBinder mToken;
+ @NonNull
+ final IBinder.DeathRecipient mDeathRecipient;
private final RemoteCallbackList<IPredictionCallback> mCallbacks =
new RemoteCallbackList<IPredictionCallback>() {
@@ -388,14 +404,16 @@ public class AppPredictionPerUserService extends
@NonNull final AppPredictionSessionId id,
@NonNull final AppPredictionContext predictionContext,
final boolean usesPeopleService,
- @NonNull final Consumer<AppPredictionSessionId> removeSessionInfoAction) {
+ @NonNull final IBinder token,
+ @NonNull final IBinder.DeathRecipient deathRecipient) {
if (DEBUG) {
Slog.d(TAG, "Creating AppPredictionSessionInfo for session Id=" + id);
}
mSessionId = id;
mPredictionContext = predictionContext;
mUsesPeopleService = usesPeopleService;
- mRemoveSessionInfoAction = removeSessionInfoAction;
+ mToken = token;
+ mDeathRecipient = deathRecipient;
}
void addCallbackLocked(IPredictionCallback callback) {
@@ -414,23 +432,38 @@ public class AppPredictionPerUserService extends
mCallbacks.unregister(callback);
}
+ boolean linkToDeath() {
+ try {
+ mToken.linkToDeath(mDeathRecipient, 0);
+ } catch (RemoteException e) {
+ if (DEBUG) {
+ Slog.w(TAG, "Caller is dead before session can be started, sessionId: "
+ + mSessionId);
+ }
+ return false;
+ }
+ return true;
+ }
+
void destroy() {
if (DEBUG) {
Slog.d(TAG, "Removing all callbacks for session Id=" + mSessionId
+ " and " + mCallbacks.getRegisteredCallbackCount() + " callbacks.");
}
+ if (mToken != null) {
+ mToken.unlinkToDeath(mDeathRecipient, 0);
+ }
mCallbacks.kill();
- mRemoveSessionInfoAction.accept(mSessionId);
}
- void resurrectSessionLocked(AppPredictionPerUserService service) {
+ void resurrectSessionLocked(AppPredictionPerUserService service, IBinder token) {
int callbackCount = mCallbacks.getRegisteredCallbackCount();
if (DEBUG) {
Slog.d(TAG, "Resurrecting remote service (" + service.getRemoteServiceLocked()
+ ") for session Id=" + mSessionId + " and "
+ callbackCount + " callbacks.");
}
- service.onCreatePredictionSessionLocked(mPredictionContext, mSessionId);
+ service.onCreatePredictionSessionLocked(mPredictionContext, mSessionId, token);
mCallbacks.broadcast(
callback -> service.registerPredictionUpdatesLocked(mSessionId, callback));
}
diff --git a/services/core/java/android/os/UserManagerInternal.java b/services/core/java/android/os/UserManagerInternal.java
index fbe8c04bd59c..38983488654e 100644
--- a/services/core/java/android/os/UserManagerInternal.java
+++ b/services/core/java/android/os/UserManagerInternal.java
@@ -227,6 +227,14 @@ public abstract class UserManagerInternal {
public abstract @NonNull List<UserInfo> getUsers(boolean excludeDying);
/**
+ * Internal implementation of getUsers does not check permissions.
+ * This improves performance for calls from inside system server which already have permissions
+ * checked.
+ */
+ public abstract @NonNull List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying,
+ boolean excludePreCreated);
+
+ /**
* Checks if the {@code callingUserId} and {@code targetUserId} are same or in same group
* and that the {@code callingUserId} is not a profile and {@code targetUserId} is enabled.
*
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 4fab067d1d3b..651f941be0b1 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -3109,6 +3109,14 @@ class AlarmManagerService extends SystemService {
mPendingBackgroundAlarms.removeAt(i);
}
}
+ for (int i = mPendingNonWakeupAlarms.size() - 1; i >= 0; i--) {
+ final Alarm a = mPendingNonWakeupAlarms.get(i);
+ if (a.matches(operation, directReceiver)) {
+ // Don't set didRemove, since this doesn't impact the scheduled alarms.
+ mPendingNonWakeupAlarms.remove(i);
+ decrementAlarmCount(a.uid, 1);
+ }
+ }
if (didRemove) {
if (DEBUG_BATCH) {
Slog.v(TAG, "remove(operation) changed bounds; rebatching");
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 678387c540ed..391923324d0c 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -4745,15 +4745,20 @@ class StorageManagerService extends IStorageManager.Stub
}
}
- public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode) {
+ public void onAppOpsChanged(int code, int uid, @Nullable String packageName, int mode,
+ int previousMode) {
final long token = Binder.clearCallingIdentity();
try {
if (mIsFuseEnabled) {
// When using FUSE, we may need to kill the app if the op changes
switch(code) {
case OP_REQUEST_INSTALL_PACKAGES:
- // Always kill regardless of op change, to remount apps /storage
- killAppForOpChange(code, uid);
+ if (previousMode == MODE_ALLOWED || mode == MODE_ALLOWED) {
+ // If we transition to/from MODE_ALLOWED, kill the app to make
+ // sure it has the correct view of /storage. Changing between
+ // MODE_DEFAULT / MODE_ERRORED is a no-op
+ killAppForOpChange(code, uid);
+ }
return;
case OP_MANAGE_EXTERNAL_STORAGE:
if (mode != MODE_ALLOWED) {
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index be080e5cce62..b5aea75d78a5 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -485,6 +485,9 @@ final class UiModeManagerService extends SystemService {
* @return True if the new value is different from the old value. False otherwise.
*/
private boolean updateNightModeFromSettingsLocked(Context context, Resources res, int userId) {
+ if (mCarModeEnabled || mCar) {
+ return false;
+ }
int oldNightMode = mNightMode;
if (mSetupWizardComplete) {
mNightMode = Secure.getIntForUser(context.getContentResolver(),
@@ -1015,7 +1018,7 @@ final class UiModeManagerService extends SystemService {
private void persistNightMode(int user) {
// Only persist setting if not in car mode
- if (mCarModeEnabled) return;
+ if (mCarModeEnabled || mCar) return;
Secure.putIntForUser(getContext().getContentResolver(),
Secure.UI_NIGHT_MODE, mNightMode, user);
Secure.putLongForUser(getContext().getContentResolver(),
@@ -1028,7 +1031,7 @@ final class UiModeManagerService extends SystemService {
private void persistNightModeOverrides(int user) {
// Only persist setting if not in car mode
- if (mCarModeEnabled) return;
+ if (mCarModeEnabled || mCar) return;
Secure.putIntForUser(getContext().getContentResolver(),
Secure.UI_NIGHT_MODE_OVERRIDE_ON, mOverrideNightModeOn ? 1 : 0, user);
Secure.putIntForUser(getContext().getContentResolver(),
@@ -1079,7 +1082,7 @@ final class UiModeManagerService extends SystemService {
}
// Override night mode in power save mode if not in car mode
- if (mPowerSave && !mCarModeEnabled) {
+ if (mPowerSave && !mCarModeEnabled && !mCar) {
uiMode &= ~Configuration.UI_MODE_NIGHT_NO;
uiMode |= Configuration.UI_MODE_NIGHT_YES;
} else {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 7d88a8a4ec01..e1bb4cda8dc2 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -1837,11 +1837,13 @@ public final class ActiveServices {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
+ " type=" + resolvedType + " conn=" + connection.asBinder()
+ " flags=0x" + Integer.toHexString(flags));
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
- + " (pid=" + Binder.getCallingPid()
+ + " (pid=" + callingPid
+ ") when binding service " + service);
}
@@ -1881,19 +1883,19 @@ public final class ActiveServices {
}
if ((flags & Context.BIND_SCHEDULE_LIKE_TOP_APP) != 0 && !isCallerSystem) {
- throw new SecurityException("Non-system caller (pid=" + Binder.getCallingPid()
+ throw new SecurityException("Non-system caller (pid=" + callingPid
+ ") set BIND_SCHEDULE_LIKE_TOP_APP when binding service " + service);
}
if ((flags & Context.BIND_ALLOW_WHITELIST_MANAGEMENT) != 0 && !isCallerSystem) {
throw new SecurityException(
- "Non-system caller " + caller + " (pid=" + Binder.getCallingPid()
+ "Non-system caller " + caller + " (pid=" + callingPid
+ ") set BIND_ALLOW_WHITELIST_MANAGEMENT when binding service " + service);
}
if ((flags & Context.BIND_ALLOW_INSTANT) != 0 && !isCallerSystem) {
throw new SecurityException(
- "Non-system caller " + caller + " (pid=" + Binder.getCallingPid()
+ "Non-system caller " + caller + " (pid=" + callingPid
+ ") set BIND_ALLOW_INSTANT when binding service " + service);
}
@@ -1909,7 +1911,7 @@ public final class ActiveServices {
ServiceLookupResult res =
retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,
- Binder.getCallingPid(), Binder.getCallingUid(), userId, true,
+ callingPid, callingUid, userId, true,
callerFg, isBindExternal, allowInstant);
if (res == null) {
return 0;
@@ -2069,7 +2071,7 @@ public final class ActiveServices {
if (!s.mAllowWhileInUsePermissionInFgs) {
s.mAllowWhileInUsePermissionInFgs =
shouldAllowWhileInUsePermissionInFgsLocked(callingPackage,
- Binder.getCallingPid(), Binder.getCallingUid(),
+ callingPid, callingUid,
service, s, false);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 44e3bbf91565..491579a5a294 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2218,17 +2218,13 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
try {
- if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
- Process.enableFreezer(false);
- }
+ mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.enableFreezer(false);
if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
"meminfo", pw)) return;
PriorityDump.dump(mPriorityDumper, fd, pw, args);
} finally {
- if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
- Process.enableFreezer(true);
- }
+ mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.enableFreezer(true);
}
}
}
@@ -2242,17 +2238,13 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
try {
- if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
- Process.enableFreezer(false);
- }
+ mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.enableFreezer(false);
if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
"gfxinfo", pw)) return;
mActivityManagerService.dumpGraphicsHardwareUsage(fd, pw, args);
} finally {
- if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
- Process.enableFreezer(true);
- }
+ mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.enableFreezer(true);
}
}
}
@@ -2266,17 +2258,13 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
try {
- if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
- Process.enableFreezer(false);
- }
+ mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.enableFreezer(false);
if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
"dbinfo", pw)) return;
mActivityManagerService.dumpDbInfo(fd, pw, args);
} finally {
- if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
- Process.enableFreezer(true);
- }
+ mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.enableFreezer(true);
}
}
}
@@ -2322,9 +2310,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
try {
- if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
- Process.enableFreezer(false);
- }
+ mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.enableFreezer(false);
if (!DumpUtils.checkDumpAndUsageStatsPermission(mActivityManagerService.mContext,
"cacheinfo", pw)) {
@@ -2333,9 +2319,7 @@ public class ActivityManagerService extends IActivityManager.Stub
mActivityManagerService.dumpBinderCacheContents(fd, pw, args);
} finally {
- if (mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.useFreezer()) {
- Process.enableFreezer(true);
- }
+ mActivityManagerService.mOomAdjuster.mCachedAppOptimizer.enableFreezer(true);
}
}
}
@@ -18630,14 +18614,14 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
- Process.enableFreezer(false);
+ mOomAdjuster.mCachedAppOptimizer.enableFreezer(false);
final RemoteCallback intermediateCallback = new RemoteCallback(
new RemoteCallback.OnResultListener() {
@Override
public void onResult(Bundle result) {
finishCallback.sendResult(result);
- Process.enableFreezer(true);
+ mOomAdjuster.mCachedAppOptimizer.enableFreezer(true);
}
}, null);
@@ -20399,4 +20383,16 @@ public class ActivityManagerService extends IActivityManager.Stub
Binder.restoreCallingIdentity(token);
}
}
+
+ @Override
+ public boolean enableAppFreezer(boolean enable) {
+ int callerUid = Binder.getCallingUid();
+
+ // Only system can toggle the freezer state
+ if (callerUid == SYSTEM_UID) {
+ return mOomAdjuster.mCachedAppOptimizer.enableFreezer(enable);
+ } else {
+ throw new SecurityException("Caller uid " + callerUid + " cannot set freezer state ");
+ }
+ }
}
diff --git a/services/core/java/com/android/server/am/CachedAppOptimizer.java b/services/core/java/com/android/server/am/CachedAppOptimizer.java
index d9fde0f6728a..8112bb854b71 100644
--- a/services/core/java/com/android/server/am/CachedAppOptimizer.java
+++ b/services/core/java/com/android/server/am/CachedAppOptimizer.java
@@ -22,6 +22,7 @@ import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import android.app.ActivityManager;
import android.app.ActivityThread;
+import android.app.ApplicationExitInfo;
import android.os.Debug;
import android.os.Handler;
import android.os.Message;
@@ -132,11 +133,15 @@ public final class CachedAppOptimizer {
static final int REPORT_UNFREEZE_MSG = 4;
//TODO:change this static definition into a configurable flag.
- static final int FREEZE_TIMEOUT_MS = 500;
+ static final int FREEZE_TIMEOUT_MS = 10000;
static final int DO_FREEZE = 1;
static final int REPORT_UNFREEZE = 2;
+ // Bitfield values for sync/async transactions reveived by frozen processes
+ static final int SYNC_RECEIVED_WHILE_FROZEN = 1;
+ static final int ASYNC_RECEIVED_WHILE_FROZEN = 2;
+
/**
* This thread must be moved to the system background cpuset.
* If that doesn't happen, it's probably going to draw a lot of power.
@@ -208,6 +213,8 @@ public final class CachedAppOptimizer {
@GuardedBy("mPhenotypeFlagLock")
private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;
private volatile boolean mUseFreezer = DEFAULT_USE_FREEZER;
+ @GuardedBy("this")
+ private int mFreezerDisableCount = 1; // Freezer is initially disabled, until enabled
private final Random mRandom = new Random();
@GuardedBy("mPhenotypeFlagLock")
@VisibleForTesting volatile float mCompactStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
@@ -420,25 +427,106 @@ public final class CachedAppOptimizer {
}
/**
- * Determines whether the freezer is correctly supported by this system
+ * Enables or disabled the app freezer.
+ * @param enable Enables the freezer if true, disables it if false.
+ * @return true if the operation completed successfully, false otherwise.
+ */
+ public synchronized boolean enableFreezer(boolean enable) {
+ if (!mUseFreezer) {
+ return false;
+ }
+
+ if (enable) {
+ mFreezerDisableCount--;
+
+ if (mFreezerDisableCount > 0) {
+ return true;
+ } else if (mFreezerDisableCount < 0) {
+ Slog.e(TAG_AM, "unbalanced call to enableFreezer, ignoring");
+ mFreezerDisableCount = 0;
+ return false;
+ }
+ } else {
+ mFreezerDisableCount++;
+
+ if (mFreezerDisableCount > 1) {
+ return true;
+ }
+ }
+
+ try {
+ enableFreezerInternal(enable);
+ return true;
+ } catch (java.lang.RuntimeException e) {
+ if (enable) {
+ mFreezerDisableCount = 0;
+ } else {
+ mFreezerDisableCount = 1;
+ }
+
+ Slog.e(TAG_AM, "Exception handling freezer state (enable: " + enable + "): "
+ + e.toString());
+ }
+
+ return false;
+ }
+
+ /**
+ * Enable or disable the freezer. When enable == false all frozen processes are unfrozen,
+ * but aren't removed from the freezer. While in this state, processes can be added or removed
+ * by using Process.setProcessFrozen(), but they wouldn't be actually frozen until the freezer
+ * is enabled. If enable == true all processes in the freezer are frozen.
+ *
+ * @param enable Specify whether to enable (true) or disable (false) the freezer.
+ *
+ * @hide
+ */
+ private static native void enableFreezerInternal(boolean enable);
+
+ /**
+ * Informs binder that a process is about to be frozen. If freezer is enabled on a process via
+ * this method, this method will synchronously dispatch all pending transactions to the
+ * specified pid. This method will not add significant latencies when unfreezing.
+ * After freezing binder calls, binder will block all transaction to the frozen pid, and return
+ * an error to the sending process.
+ *
+ * @param pid the target pid for which binder transactions are to be frozen
+ * @param freeze specifies whether to flush transactions and then freeze (true) or unfreeze
+ * binder for the specificed pid.
+ *
+ * @throws RuntimeException in case a flush/freeze operation could not complete successfully.
+ */
+ private static native void freezeBinder(int pid, boolean freeze);
+
+ /**
+ * Retrieves binder freeze info about a process.
+ * @param pid the pid for which binder freeze info is to be retrieved.
+ *
+ * @throws RuntimeException if the operation could not complete successfully.
+ * @return a bit field reporting the binder freeze info for the process.
+ */
+ private static native int getBinderFreezeInfo(int pid);
+
+ /**
+ * Determines whether the freezer is supported by this system
*/
public static boolean isFreezerSupported() {
boolean supported = false;
FileReader fr = null;
try {
- fr = new FileReader("/dev/freezer/frozen/freezer.killable");
- int i = fr.read();
+ fr = new FileReader("/sys/fs/cgroup/freezer/cgroup.freeze");
+ char state = (char) fr.read();
- if ((char) i == '1') {
+ if (state == '1' || state == '0') {
supported = true;
} else {
- Slog.w(TAG_AM, "Freezer killability is turned off, disabling freezer");
+ Slog.e(TAG_AM, "unexpected value in cgroup.freeze");
}
} catch (java.io.FileNotFoundException e) {
- Slog.d(TAG_AM, "Freezer.killable not present, disabling freezer");
+ Slog.d(TAG_AM, "cgroup.freeze not present");
} catch (Exception e) {
- Slog.d(TAG_AM, "Unable to read freezer.killable, disabling freezer: " + e.toString());
+ Slog.d(TAG_AM, "unable to read cgroup.freeze: " + e.toString());
}
if (fr != null) {
@@ -471,6 +559,8 @@ public final class CachedAppOptimizer {
if (mUseFreezer && mFreezeHandler == null) {
Slog.d(TAG_AM, "Freezer enabled");
+ enableFreezer(true);
+
if (!mCachedAppOptimizerThread.isAlive()) {
mCachedAppOptimizerThread.start();
}
@@ -479,6 +569,8 @@ public final class CachedAppOptimizer {
Process.setThreadGroupAndCpuset(mCachedAppOptimizerThread.getThreadId(),
Process.THREAD_GROUP_SYSTEM);
+ } else {
+ enableFreezer(false);
}
}
@@ -651,6 +743,37 @@ public final class CachedAppOptimizer {
return;
}
+ boolean processKilled = false;
+
+ try {
+ int freezeInfo = getBinderFreezeInfo(app.pid);
+
+ if ((freezeInfo & SYNC_RECEIVED_WHILE_FROZEN) != 0) {
+ Slog.d(TAG_AM, "pid " + app.pid + " " + app.processName + " "
+ + " received sync transactions while frozen, killing");
+ app.kill("Sync transaction while in frozen state",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ processKilled = true;
+ }
+
+ if ((freezeInfo & ASYNC_RECEIVED_WHILE_FROZEN) != 0) {
+ Slog.d(TAG_AM, "pid " + app.pid + " " + app.processName + " "
+ + " received async transactions while frozen");
+ }
+ } catch (Exception e) {
+ Slog.d(TAG_AM, "Unable to query binder frozen info for pid " + app.pid + " "
+ + app.processName + ". Killing it. Exception: " + e);
+ app.kill("Unable to query binder frozen stats",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ processKilled = true;
+ }
+
+ if (processKilled) {
+ return;
+ }
+
long freezeTime = app.freezeUnfreezeTime;
try {
@@ -664,6 +787,17 @@ public final class CachedAppOptimizer {
}
if (!app.frozen) {
+ try {
+ freezeBinder(app.pid, false);
+ } catch (RuntimeException e) {
+ Slog.e(TAG_AM, "Unable to unfreeze binder for " + app.pid + " " + app.processName
+ + ". Killing it");
+ app.kill("Unable to unfreeze",
+ ApplicationExitInfo.REASON_OTHER,
+ ApplicationExitInfo.SUBREASON_INVALID_STATE, true);
+ return;
+ }
+
if (DEBUG_FREEZER) {
Slog.d(TAG_AM, "sync unfroze " + app.pid + " " + app.processName);
}
@@ -976,6 +1110,14 @@ public final class CachedAppOptimizer {
return;
}
+ try {
+ freezeBinder(pid, true);
+ } catch (RuntimeException e) {
+ // TODO: it might be preferable to kill the target pid in this case
+ Slog.e(TAG_AM, "Unable to freeze binder for " + pid + " " + name);
+ return;
+ }
+
if (pid == 0 || proc.frozen) {
// Already frozen or not a real process, either one being
// launched or one being killed
diff --git a/services/core/java/com/android/server/am/PendingTempWhitelists.java b/services/core/java/com/android/server/am/PendingTempWhitelists.java
index b36e3c7b9e35..50d58f02baa7 100644
--- a/services/core/java/com/android/server/am/PendingTempWhitelists.java
+++ b/services/core/java/com/android/server/am/PendingTempWhitelists.java
@@ -32,13 +32,13 @@ final class PendingTempWhitelists {
void put(int uid, ActivityManagerService.PendingTempWhitelist value) {
mPendingTempWhitelist.put(uid, value);
- mService.mAtmInternal.onUidAddedToPendingTempWhitelist(uid, value.tag);
+ mService.mAtmInternal.onUidAddedToPendingTempAllowlist(uid, value.tag);
}
void removeAt(int index) {
final int uid = mPendingTempWhitelist.keyAt(index);
mPendingTempWhitelist.removeAt(index);
- mService.mAtmInternal.onUidRemovedFromPendingTempWhitelist(uid);
+ mService.mAtmInternal.onUidRemovedFromPendingTempAllowlist(uid);
}
ActivityManagerService.PendingTempWhitelist get(int uid) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index c5bdb9edd069..6cecb6aedd45 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -39,6 +39,7 @@ import static android.app.AppOpsManager.OP_FLAG_TRUSTED_PROXIED;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.OP_PLAY_AUDIO;
import static android.app.AppOpsManager.OP_RECORD_AUDIO;
+import static android.app.AppOpsManager.OP_RECORD_AUDIO_HOTWORD;
import static android.app.AppOpsManager.OpEventProxyInfo;
import static android.app.AppOpsManager.RestrictionBypass;
import static android.app.AppOpsManager.SAMPLING_STRATEGY_BOOT_TIME_SAMPLING;
@@ -2198,6 +2199,7 @@ public class AppOpsService extends IAppOpsService.Stub {
updatePermissionRevokedCompat(uid, code, mode);
}
+ int previousMode;
synchronized (this) {
final int defaultMode = AppOpsManager.opToDefaultMode(code);
@@ -2206,12 +2208,14 @@ public class AppOpsService extends IAppOpsService.Stub {
if (mode == defaultMode) {
return;
}
+ previousMode = AppOpsManager.MODE_DEFAULT;
uidState = new UidState(uid);
uidState.opModes = new SparseIntArray();
uidState.opModes.put(code, mode);
mUidStates.put(uid, uidState);
scheduleWriteLocked();
} else if (uidState.opModes == null) {
+ previousMode = AppOpsManager.MODE_DEFAULT;
if (mode != defaultMode) {
uidState.opModes = new SparseIntArray();
uidState.opModes.put(code, mode);
@@ -2221,6 +2225,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (uidState.opModes.indexOfKey(code) >= 0 && uidState.opModes.get(code) == mode) {
return;
}
+ previousMode = uidState.opModes.get(code);
if (mode == defaultMode) {
uidState.opModes.delete(code);
if (uidState.opModes.size() <= 0) {
@@ -2235,7 +2240,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
notifyOpChangedForAllPkgsInUid(code, uid, false, permissionPolicyCallback);
- notifyOpChangedSync(code, uid, null, mode);
+ notifyOpChangedSync(code, uid, null, mode, previousMode);
}
/**
@@ -2414,11 +2419,12 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode) {
+ private void notifyOpChangedSync(int code, int uid, @NonNull String packageName, int mode,
+ int previousMode) {
final StorageManagerInternal storageManagerInternal =
LocalServices.getService(StorageManagerInternal.class);
if (storageManagerInternal != null) {
- storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode);
+ storageManagerInternal.onAppOpsChanged(code, uid, packageName, mode, previousMode);
}
}
@@ -2450,11 +2456,13 @@ public class AppOpsService extends IAppOpsService.Stub {
return;
}
+ int previousMode = AppOpsManager.MODE_DEFAULT;
synchronized (this) {
UidState uidState = getUidStateLocked(uid, false);
Op op = getOpLocked(code, uid, packageName, null, bypass, true);
if (op != null) {
if (op.mode != mode) {
+ previousMode = op.mode;
op.mode = mode;
if (uidState != null) {
uidState.evalForegroundOps(mOpModeWatchers);
@@ -2491,7 +2499,7 @@ public class AppOpsService extends IAppOpsService.Stub {
this, repCbs, code, uid, packageName));
}
- notifyOpChangedSync(code, uid, packageName, mode);
+ notifyOpChangedSync(code, uid, packageName, mode, previousMode);
}
private void notifyOpChanged(ArraySet<ModeCallback> callbacks, int code,
@@ -2534,7 +2542,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
private static ArrayList<ChangeRec> addChange(ArrayList<ChangeRec> reports,
- int op, int uid, String packageName) {
+ int op, int uid, String packageName, int previousMode) {
boolean duplicate = false;
if (reports == null) {
reports = new ArrayList<>();
@@ -2549,7 +2557,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
if (!duplicate) {
- reports.add(new ChangeRec(op, uid, packageName));
+ reports.add(new ChangeRec(op, uid, packageName, previousMode));
}
return reports;
@@ -2557,7 +2565,7 @@ public class AppOpsService extends IAppOpsService.Stub {
private static HashMap<ModeCallback, ArrayList<ChangeRec>> addCallbacks(
HashMap<ModeCallback, ArrayList<ChangeRec>> callbacks,
- int op, int uid, String packageName, ArraySet<ModeCallback> cbs) {
+ int op, int uid, String packageName, int previousMode, ArraySet<ModeCallback> cbs) {
if (cbs == null) {
return callbacks;
}
@@ -2568,7 +2576,7 @@ public class AppOpsService extends IAppOpsService.Stub {
for (int i=0; i<N; i++) {
ModeCallback cb = cbs.valueAt(i);
ArrayList<ChangeRec> reports = callbacks.get(cb);
- ArrayList<ChangeRec> changed = addChange(reports, op, uid, packageName);
+ ArrayList<ChangeRec> changed = addChange(reports, op, uid, packageName, previousMode);
if (changed != reports) {
callbacks.put(cb, changed);
}
@@ -2580,11 +2588,13 @@ public class AppOpsService extends IAppOpsService.Stub {
final int op;
final int uid;
final String pkg;
+ final int previous_mode;
- ChangeRec(int _op, int _uid, String _pkg) {
+ ChangeRec(int _op, int _uid, String _pkg, int _previous_mode) {
op = _op;
uid = _uid;
pkg = _pkg;
+ previous_mode = _previous_mode;
}
}
@@ -2620,18 +2630,19 @@ public class AppOpsService extends IAppOpsService.Stub {
for (int j = uidOpCount - 1; j >= 0; j--) {
final int code = opModes.keyAt(j);
if (AppOpsManager.opAllowsReset(code)) {
+ int previousMode = opModes.valueAt(j);
opModes.removeAt(j);
if (opModes.size() <= 0) {
uidState.opModes = null;
}
for (String packageName : getPackagesForUid(uidState.uid)) {
callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
- mOpModeWatchers.get(code));
+ previousMode, mOpModeWatchers.get(code));
callbacks = addCallbacks(callbacks, code, uidState.uid, packageName,
- mPackageModeWatchers.get(packageName));
+ previousMode, mPackageModeWatchers.get(packageName));
allChanges = addChange(allChanges, code, uidState.uid,
- packageName);
+ packageName, previousMode);
}
}
}
@@ -2662,16 +2673,18 @@ public class AppOpsService extends IAppOpsService.Stub {
Op curOp = pkgOps.valueAt(j);
if (AppOpsManager.opAllowsReset(curOp.op)
&& curOp.mode != AppOpsManager.opToDefaultMode(curOp.op)) {
+ int previousMode = curOp.mode;
curOp.mode = AppOpsManager.opToDefaultMode(curOp.op);
changed = true;
uidChanged = true;
final int uid = curOp.uidState.uid;
callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
- mOpModeWatchers.get(curOp.op));
+ previousMode, mOpModeWatchers.get(curOp.op));
callbacks = addCallbacks(callbacks, curOp.op, uid, packageName,
- mPackageModeWatchers.get(packageName));
+ previousMode, mPackageModeWatchers.get(packageName));
- allChanges = addChange(allChanges, curOp.op, uid, packageName);
+ allChanges = addChange(allChanges, curOp.op, uid, packageName,
+ previousMode);
curOp.removeAttributionsWithNoTime();
if (curOp.mAttributions.isEmpty()) {
pkgOps.removeAt(j);
@@ -2712,7 +2725,7 @@ public class AppOpsService extends IAppOpsService.Stub {
for (int i = 0; i < numChanges; i++) {
ChangeRec change = allChanges.get(i);
notifyOpChangedSync(change.op, change.uid, change.pkg,
- AppOpsManager.opToDefaultMode(change.op));
+ AppOpsManager.opToDefaultMode(change.op), change.previous_mode);
}
}
}
@@ -3400,7 +3413,19 @@ public class AppOpsService extends IAppOpsService.Stub {
verifyIncomingOp(code);
String resolvedPackageName = resolvePackageName(uid, packageName);
if (resolvedPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
+ return AppOpsManager.MODE_IGNORED;
+ }
+
+ // As a special case for OP_RECORD_AUDIO_HOTWORD, which we use only for attribution
+ // purposes and not as a check, also make sure that the caller is allowed to access
+ // the data gated by OP_RECORD_AUDIO.
+ //
+ // TODO: Revert this change before Android 12.
+ if (code == OP_RECORD_AUDIO_HOTWORD) {
+ int result = checkOperation(OP_RECORD_AUDIO, uid, packageName);
+ if (result != AppOpsManager.MODE_ALLOWED) {
+ return result;
+ }
}
RestrictionBypass bypass;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 45f95fd3f663..074d3fe10816 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -224,12 +224,35 @@ import java.util.concurrent.atomic.AtomicBoolean;
if (!addSpeakerphoneClient(cb, pid, on)) {
return false;
}
+ if (on) {
+ // Cancel BT SCO ON request by this same client: speakerphone and BT SCO routes
+ // are mutually exclusive.
+ // See symmetrical operation for startBluetoothScoForClient_Sync().
+ mBtHelper.stopBluetoothScoForPid(pid);
+ }
final boolean wasOn = isSpeakerphoneOn();
updateSpeakerphoneOn(eventSource);
return (wasOn != isSpeakerphoneOn());
}
}
+ /**
+ * Turns speakerphone off for a given pid and update speakerphone state.
+ * @param pid
+ */
+ @GuardedBy("mDeviceStateLock")
+ private void setSpeakerphoneOffForPid(int pid) {
+ SpeakerphoneClient client = getSpeakerphoneClientForPid(pid);
+ if (client == null) {
+ return;
+ }
+ client.unregisterDeathRecipient();
+ mSpeakerphoneClients.remove(client);
+ final String eventSource = new StringBuilder("setSpeakerphoneOffForPid(")
+ .append(pid).append(")").toString();
+ updateSpeakerphoneOn(eventSource);
+ }
+
@GuardedBy("mDeviceStateLock")
private void updateSpeakerphoneOn(String eventSource) {
if (isSpeakerphoneOnRequested()) {
@@ -476,8 +499,8 @@ import java.util.concurrent.atomic.AtomicBoolean;
sendIIMsgNoDelay(MSG_II_SET_HEARING_AID_VOLUME, SENDMSG_REPLACE, index, streamType);
}
- /*package*/ void postSetModeOwnerPid(int pid) {
- sendIMsgNoDelay(MSG_I_SET_MODE_OWNER_PID, SENDMSG_REPLACE, pid);
+ /*package*/ void postSetModeOwnerPid(int pid, int mode) {
+ sendIIMsgNoDelay(MSG_I_SET_MODE_OWNER_PID, SENDMSG_REPLACE, pid, mode);
}
/*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) {
@@ -488,6 +511,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
/*package*/ void startBluetoothScoForClient_Sync(IBinder cb, int scoAudioMode,
@NonNull String eventSource) {
synchronized (mDeviceStateLock) {
+ // Cancel speakerphone ON request by this same client: speakerphone and BT SCO routes
+ // are mutually exclusive.
+ // See symmetrical operation for setSpeakerphoneOn(true).
+ setSpeakerphoneOffForPid(Binder.getCallingPid());
mBtHelper.startBluetoothScoForClient(cb, scoAudioMode, eventSource);
}
}
@@ -949,7 +976,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
synchronized (mDeviceStateLock) {
if (mModeOwnerPid != msg.arg1) {
mModeOwnerPid = msg.arg1;
- updateSpeakerphoneOn("setNewModeOwner");
+ if (msg.arg2 != AudioSystem.MODE_RINGTONE) {
+ updateSpeakerphoneOn("setNewModeOwner");
+ }
if (mModeOwnerPid != 0) {
mBtHelper.disconnectBluetoothSco(mModeOwnerPid);
}
@@ -1379,6 +1408,16 @@ import java.util.concurrent.atomic.AtomicBoolean;
return false;
}
+ @GuardedBy("mDeviceStateLock")
+ private SpeakerphoneClient getSpeakerphoneClientForPid(int pid) {
+ for (SpeakerphoneClient cl : mSpeakerphoneClients) {
+ if (cl.getPid() == pid) {
+ return cl;
+ }
+ }
+ return null;
+ }
+
// List of clients requesting speakerPhone ON
@GuardedBy("mDeviceStateLock")
private final @NonNull ArrayList<SpeakerphoneClient> mSpeakerphoneClients =
diff --git a/services/core/java/com/android/server/audio/AudioEventLogger.java b/services/core/java/com/android/server/audio/AudioEventLogger.java
index 9ebd75bd0f64..af0e978726e3 100644
--- a/services/core/java/com/android/server/audio/AudioEventLogger.java
+++ b/services/core/java/com/android/server/audio/AudioEventLogger.java
@@ -60,7 +60,36 @@ public class AudioEventLogger {
* @return the same instance of the event
*/
public Event printLog(String tag) {
- Log.i(tag, eventToString());
+ return printLog(ALOGI, tag);
+ }
+
+ public static final int ALOGI = 0;
+ public static final int ALOGE = 1;
+ public static final int ALOGW = 2;
+ public static final int ALOGV = 3;
+
+ /**
+ * Same as {@link #printLog(String)} with a log type
+ * @param type one of {@link #ALOGI}, {@link #ALOGE}, {@link #ALOGV}
+ * @param tag
+ * @return
+ */
+ public Event printLog(int type, String tag) {
+ switch (type) {
+ case ALOGI:
+ Log.i(tag, eventToString());
+ break;
+ case ALOGE:
+ Log.e(tag, eventToString());
+ break;
+ case ALOGW:
+ Log.w(tag, eventToString());
+ break;
+ case ALOGV:
+ default:
+ Log.v(tag, eventToString());
+ break;
+ }
return this;
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index c4eca605206d..75c27603d785 100755
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -26,6 +26,10 @@ import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE;
import static android.provider.Settings.Secure.VOLUME_HUSH_OFF;
import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE;
+import static com.android.server.audio.AudioEventLogger.Event.ALOGE;
+import static com.android.server.audio.AudioEventLogger.Event.ALOGI;
+import static com.android.server.audio.AudioEventLogger.Event.ALOGW;
+
import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -284,6 +288,7 @@ public class AudioService extends IAudioService.Stub
private static final int MSG_PLAYBACK_CONFIG_CHANGE = 29;
private static final int MSG_BROADCAST_MICROPHONE_MUTE = 30;
private static final int MSG_CHECK_MODE_FOR_UID = 31;
+ private static final int MSG_REINIT_VOLUMES = 32;
// start of messages handled under wakelock
// these messages can only be queued, i.e. sent with queueMsgUnderWakeLock(),
// and not with sendMsg(..., ..., SENDMSG_QUEUE, ...)
@@ -673,6 +678,7 @@ public class AudioService extends IAudioService.Stub
public AudioService(Context context, AudioSystemAdapter audioSystem,
SystemServerAdapter systemServer) {
+ sLifecycleLogger.log(new AudioEventLogger.StringEvent("AudioService()"));
mContext = context;
mContentResolver = context.getContentResolver();
mAppOps = (AppOpsManager)context.getSystemService(Context.APP_OPS_SERVICE);
@@ -892,6 +898,9 @@ public class AudioService extends IAudioService.Stub
mPrescaleAbsoluteVolume[i] = preScale[i];
}
}
+
+ // check on volume initialization
+ checkVolumeRangeInitialization("AudioService()");
}
public void systemReady() {
@@ -1019,11 +1028,15 @@ public class AudioService extends IAudioService.Stub
if (!mSystemReady ||
(AudioSystem.checkAudioFlinger() != AudioSystem.AUDIO_STATUS_OK)) {
Log.e(TAG, "Audioserver died.");
+ sLifecycleLogger.log(new AudioEventLogger.StringEvent(
+ "onAudioServerDied() audioserver died"));
sendMsg(mAudioHandler, MSG_AUDIO_SERVER_DIED, SENDMSG_NOOP, 0, 0,
null, 500);
return;
}
- Log.e(TAG, "Audioserver started.");
+ Log.i(TAG, "Audioserver started.");
+ sLifecycleLogger.log(new AudioEventLogger.StringEvent(
+ "onAudioServerDied() audioserver started"));
updateAudioHalPids();
@@ -1058,14 +1071,7 @@ public class AudioService extends IAudioService.Stub
mDeviceBroker.setForceUse_Async(AudioSystem.FOR_SYSTEM, forSys, "onAudioServerDied");
// Restore stream volumes
- int numStreamTypes = AudioSystem.getNumStreamTypes();
- for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
- VolumeStreamState streamState = mStreamStates[streamType];
- AudioSystem.initStreamVolume(
- streamType, streamState.mIndexMin / 10, streamState.mIndexMax / 10);
-
- streamState.applyAllVolumes();
- }
+ onReinitVolumes("after audioserver restart");
// Restore audio volume groups
restoreVolumeGroups();
@@ -1163,6 +1169,72 @@ public class AudioService extends IAudioService.Stub
setMicMuteFromSwitchInput();
}
+ private void onReinitVolumes(@NonNull String caller) {
+ final int numStreamTypes = AudioSystem.getNumStreamTypes();
+ // keep track of any error during stream volume initialization
+ int status = AudioSystem.AUDIO_STATUS_OK;
+ for (int streamType = numStreamTypes - 1; streamType >= 0; streamType--) {
+ VolumeStreamState streamState = mStreamStates[streamType];
+ final int res = AudioSystem.initStreamVolume(
+ streamType, streamState.mIndexMin / 10, streamState.mIndexMax / 10);
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ status = res;
+ Log.e(TAG, "Failed to initStreamVolume (" + res + ") for stream " + streamType);
+ // stream volume initialization failed, no need to try the others, it will be
+ // attempted again when MSG_REINIT_VOLUMES is handled
+ break;
+ }
+ streamState.applyAllVolumes();
+ }
+
+ // did it work? check based on status
+ if (status != AudioSystem.AUDIO_STATUS_OK) {
+ sLifecycleLogger.log(new AudioEventLogger.StringEvent(
+ caller + ": initStreamVolume failed with " + status + " will retry")
+ .printLog(ALOGE, TAG));
+ sendMsg(mAudioHandler, MSG_REINIT_VOLUMES, SENDMSG_NOOP, 0, 0,
+ caller /*obj*/, 2 * INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
+ return;
+ }
+
+ // did it work? check based on min/max values of some basic streams
+ if (!checkVolumeRangeInitialization(caller)) {
+ return;
+ }
+
+ // success
+ sLifecycleLogger.log(new AudioEventLogger.StringEvent(
+ caller + ": initStreamVolume succeeded").printLog(ALOGI, TAG));
+ }
+
+ /**
+ * Check volume ranges were properly initialized
+ * @return true if volume ranges were successfully initialized
+ */
+ private boolean checkVolumeRangeInitialization(String caller) {
+ boolean success = true;
+ final int[] basicStreams = { AudioSystem.STREAM_ALARM, AudioSystem.STREAM_RING,
+ AudioSystem.STREAM_MUSIC, AudioSystem.STREAM_VOICE_CALL,
+ AudioSystem.STREAM_ACCESSIBILITY };
+ for (int streamType : basicStreams) {
+ final AudioAttributes aa = new AudioAttributes.Builder()
+ .setInternalLegacyStreamType(streamType).build();
+ if (AudioSystem.getMaxVolumeIndexForAttributes(aa) < 0
+ || AudioSystem.getMinVolumeIndexForAttributes(aa) < 0) {
+ success = false;
+ break;
+ }
+ }
+ if (!success) {
+ sLifecycleLogger.log(new AudioEventLogger.StringEvent(
+ caller + ": initStreamVolume succeeded but invalid mix/max levels, will retry")
+ .printLog(ALOGW, TAG));
+ sendMsg(mAudioHandler, MSG_REINIT_VOLUMES, SENDMSG_NOOP, 0, 0,
+ caller /*obj*/, 2 * INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
+ }
+ return success;
+ }
+
private void onDispatchAudioServerStateChange(boolean state) {
synchronized (mAudioServerStateListeners) {
for (AsdProxy asdp : mAudioServerStateListeners.values()) {
@@ -3680,13 +3752,15 @@ public class AudioService extends IAudioService.Stub
private final IBinder mCb; // To be notified of client's death
private final int mPid;
private final int mUid;
- private String mPackage;
+ private final boolean mIsPrivileged;
+ private final String mPackage;
private int mMode = AudioSystem.MODE_NORMAL; // Current mode set by this client
- SetModeDeathHandler(IBinder cb, int pid, int uid, String caller) {
+ SetModeDeathHandler(IBinder cb, int pid, int uid, boolean isPrivileged, String caller) {
mCb = cb;
mPid = pid;
mUid = uid;
+ mIsPrivileged = isPrivileged;
mPackage = caller;
}
@@ -3698,12 +3772,13 @@ public class AudioService extends IAudioService.Stub
if (index < 0) {
Log.w(TAG, "unregistered setMode() client died");
} else {
- newModeOwnerPid = setModeInt(AudioSystem.MODE_NORMAL, mCb, mPid, mUid, TAG);
+ newModeOwnerPid = setModeInt(
+ AudioSystem.MODE_NORMAL, mCb, mPid, mUid, mIsPrivileged, TAG);
}
}
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
// SCO connections not started by the application changing the mode when pid changes
- mDeviceBroker.postSetModeOwnerPid(newModeOwnerPid);
+ mDeviceBroker.postSetModeOwnerPid(newModeOwnerPid, AudioService.this.getMode());
}
public int getPid() {
@@ -3729,6 +3804,10 @@ public class AudioService extends IAudioService.Stub
public String getPackage() {
return mPackage;
}
+
+ public boolean isPrivileged() {
+ return mIsPrivileged;
+ }
}
/** @see AudioManager#setMode(int) */
@@ -3780,18 +3859,19 @@ public class AudioService extends IAudioService.Stub
+ " without permission or being mode owner");
return;
}
- newModeOwnerPid = setModeInt(
- mode, cb, callingPid, Binder.getCallingUid(), callingPackage);
+ newModeOwnerPid = setModeInt(mode, cb, callingPid, Binder.getCallingUid(),
+ hasModifyPhoneStatePermission, callingPackage);
}
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all
// SCO connections not started by the application changing the mode when pid changes
- mDeviceBroker.postSetModeOwnerPid(newModeOwnerPid);
+ mDeviceBroker.postSetModeOwnerPid(newModeOwnerPid, getMode());
}
// setModeInt() returns a valid PID if the audio mode was successfully set to
// any mode other than NORMAL.
@GuardedBy("mDeviceBroker.mSetModeLock")
- private int setModeInt(int mode, IBinder cb, int pid, int uid, String caller) {
+ private int setModeInt(
+ int mode, IBinder cb, int pid, int uid, boolean isPrivileged, String caller) {
if (DEBUG_MODE) {
Log.v(TAG, "setModeInt(mode=" + mode + ", pid=" + pid
+ ", uid=" + uid + ", caller=" + caller + ")");
@@ -3843,7 +3923,7 @@ public class AudioService extends IAudioService.Stub
}
} else {
if (hdlr == null) {
- hdlr = new SetModeDeathHandler(cb, pid, uid, caller);
+ hdlr = new SetModeDeathHandler(cb, pid, uid, isPrivileged, caller);
}
// Register for client death notification
try {
@@ -3902,7 +3982,8 @@ public class AudioService extends IAudioService.Stub
// change of mode may require volume to be re-applied on some devices
updateAbsVolumeMultiModeDevices(oldMode, actualMode);
- if (actualMode == AudioSystem.MODE_IN_COMMUNICATION) {
+ if (actualMode == AudioSystem.MODE_IN_COMMUNICATION
+ && !hdlr.isPrivileged()) {
sendMsg(mAudioHandler,
MSG_CHECK_MODE_FOR_UID,
SENDMSG_QUEUE,
@@ -5570,7 +5651,15 @@ public class AudioService extends IAudioService.Stub
mIndexMin = MIN_STREAM_VOLUME[streamType] * 10;
mIndexMinNoPerm = mIndexMin; // may be overwritten later in updateNoPermMinIndex()
mIndexMax = MAX_STREAM_VOLUME[streamType] * 10;
- AudioSystem.initStreamVolume(streamType, mIndexMin / 10, mIndexMax / 10);
+ final int status = AudioSystem.initStreamVolume(
+ streamType, mIndexMin / 10, mIndexMax / 10);
+ if (status != AudioSystem.AUDIO_STATUS_OK) {
+ sLifecycleLogger.log(new AudioEventLogger.StringEvent(
+ "VSS() stream:" + streamType + " initStreamVolume=" + status)
+ .printLog(ALOGE, TAG));
+ sendMsg(mAudioHandler, MSG_REINIT_VOLUMES, SENDMSG_NOOP, 0, 0,
+ "VSS()" /*obj*/, 2 * INDICATE_SYSTEM_READY_RETRY_DELAY_MS);
+ }
readSettings();
mVolumeChanged = new Intent(AudioManager.VOLUME_CHANGED_ACTION);
@@ -6419,11 +6508,15 @@ public class AudioService extends IAudioService.Stub
CHECK_MODE_FOR_UID_PERIOD_MS);
break;
}
- // For now just log the fact that an app is hogging the audio mode.
- // TODO(b/160260850): remove abusive app from audio mode stack.
+ setModeInt(AudioSystem.MODE_NORMAL, h.getBinder(), h.getPid(), h.getUid(),
+ h.isPrivileged(), "MSG_CHECK_MODE_FOR_UID");
mModeLogger.log(new PhoneStateEvent(h.getPackage(), h.getPid()));
}
break;
+
+ case MSG_REINIT_VOLUMES:
+ onReinitVolumes((String) msg.obj);
+ break;
}
}
}
@@ -7354,12 +7447,16 @@ public class AudioService extends IAudioService.Stub
//==========================================================================================
// AudioService logging and dumpsys
//==========================================================================================
+ static final int LOG_NB_EVENTS_LIFECYCLE = 20;
static final int LOG_NB_EVENTS_PHONE_STATE = 20;
static final int LOG_NB_EVENTS_DEVICE_CONNECTION = 30;
static final int LOG_NB_EVENTS_FORCE_USE = 20;
static final int LOG_NB_EVENTS_VOLUME = 40;
static final int LOG_NB_EVENTS_DYN_POLICY = 10;
+ static final AudioEventLogger sLifecycleLogger = new AudioEventLogger(LOG_NB_EVENTS_LIFECYCLE,
+ "audio services lifecycle");
+
final private AudioEventLogger mModeLogger = new AudioEventLogger(LOG_NB_EVENTS_PHONE_STATE,
"phone state (logged after successful call to AudioSystem.setPhoneState(int, int))");
@@ -7436,6 +7533,7 @@ public class AudioService extends IAudioService.Stub
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+ sLifecycleLogger.dump(pw);
if (mAudioHandler != null) {
pw.println("\nMessage handler (watch for unhandled messages):");
mAudioHandler.dump(new PrintWriterPrinter(pw), " ");
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index b4c41b274dbe..7616557ac80f 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -432,19 +432,36 @@ public class BtHelper {
// and this must be done on behalf of system server to make sure permissions are granted.
final long ident = Binder.clearCallingIdentity();
if (client != null) {
- AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource));
- client.requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
- SCO_MODE_VIRTUAL_CALL);
- // If a disconnection is pending, the client will be removed whne clearAllScoClients()
- // is called form receiveBtEvent()
- if (mScoAudioState != SCO_STATE_DEACTIVATE_REQ
- && mScoAudioState != SCO_STATE_DEACTIVATING) {
- client.remove(false /*stop */, true /*unregister*/);
- }
+ stopAndRemoveClient(client, eventSource);
}
Binder.restoreCallingIdentity(ident);
}
+ // @GuardedBy("AudioDeviceBroker.mSetModeLock")
+ @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
+ /*package*/ synchronized void stopBluetoothScoForPid(int pid) {
+ ScoClient client = getScoClientForPid(pid);
+ if (client == null) {
+ return;
+ }
+ final String eventSource = new StringBuilder("stopBluetoothScoForPid(")
+ .append(pid).append(")").toString();
+ stopAndRemoveClient(client, eventSource);
+ }
+
+ @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
+ // @GuardedBy("BtHelper.this")
+ private void stopAndRemoveClient(ScoClient client, @NonNull String eventSource) {
+ AudioService.sDeviceLogger.log(new AudioEventLogger.StringEvent(eventSource));
+ client.requestScoState(BluetoothHeadset.STATE_AUDIO_DISCONNECTED,
+ SCO_MODE_VIRTUAL_CALL);
+ // If a disconnection is pending, the client will be removed when clearAllScoClients()
+ // is called form receiveBtEvent()
+ if (mScoAudioState != SCO_STATE_DEACTIVATE_REQ
+ && mScoAudioState != SCO_STATE_DEACTIVATING) {
+ client.remove(false /*stop */, true /*unregister*/);
+ }
+ }
/*package*/ synchronized void setHearingAidVolume(int index, int streamType) {
if (mHearingAid == null) {
@@ -974,6 +991,16 @@ public class BtHelper {
return null;
}
+ @GuardedBy("BtHelper.this")
+ private ScoClient getScoClientForPid(int pid) {
+ for (ScoClient cl : mScoClients) {
+ if (cl.getPid() == pid) {
+ return cl;
+ }
+ }
+ return null;
+ }
+
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
//@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
@GuardedBy("BtHelper.this")
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index e5a1898459a2..281f4b6b1d51 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -33,6 +33,7 @@ import android.content.Intent;
import android.content.pm.UserInfo;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
+import android.hardware.biometrics.BiometricFaceConstants;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricServiceLockoutResetCallback;
import android.hardware.biometrics.IBiometricServiceReceiverInternal;
@@ -604,6 +605,8 @@ public class FaceService extends BiometricServiceBase {
return false;
}
+ getFeature(userId, BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION,
+ null /* receiver */, opPackageName);
return FaceService.this.hasEnrolledBiometrics(userId);
}
@@ -692,7 +695,20 @@ public class FaceService extends BiometricServiceBase {
if (mDaemon != null) {
try {
OptionalBool result = mDaemon.getFeature(feature, faceId);
- receiver.onFeatureGet(result.status == Status.OK, feature, result.value);
+ if (receiver != null) {
+ receiver.onFeatureGet(result.status == Status.OK,
+ feature, result.value);
+ }
+
+ if (result.status == Status.OK
+ && feature == BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION) {
+ final int settingsValue = result.value ? 1 : 0;
+ Slog.d(TAG, "Updating attention value for user: " + mCurrentUserId
+ + " to value: " + settingsValue);
+ Settings.Secure.putIntForUser(getContext().getContentResolver(),
+ Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
+ settingsValue, mCurrentUserId);
+ }
} catch (RemoteException e) {
Slog.e(getTag(), "Unable to getRequireAttention", e);
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 24661d69a78e..852868616afd 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -86,6 +86,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.EventLog;
import android.util.IntArray;
import android.util.Pair;
import android.util.Slog;
@@ -2191,10 +2192,16 @@ public final class DisplayManagerService extends SystemService {
}
}
- if (callingUid == Process.SYSTEM_UID
- || checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
- flags |= VIRTUAL_DISPLAY_FLAG_TRUSTED;
- } else {
+ if (callingUid != Process.SYSTEM_UID && (flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) != 0) {
+ if (!checkCallingPermission(ADD_TRUSTED_DISPLAY, "createVirtualDisplay()")) {
+ EventLog.writeEvent(0x534e4554, "162627132", callingUid,
+ "Attempt to create a trusted display without holding permission!");
+ throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
+ + "create a trusted virtual display.");
+ }
+ }
+
+ if ((flags & VIRTUAL_DISPLAY_FLAG_TRUSTED) == 0) {
flags &= ~VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
}
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index 2672f848f192..cf03c607a368 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -948,7 +948,7 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
if (debug) {
Slog.d(mTag, "Eagerly recreating service for user " + userId);
}
- getServiceForUserLocked(userId);
+ updateCachedServiceLocked(userId);
}
}
onServicePackageRestartedLocked(userId);
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index 817902d9d566..b61c6a7ca569 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -205,8 +205,13 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
}
if (DEBUG_INTEGRITY_COMPONENT) {
- Slog.i(TAG, String.format("Successfully pushed rule set: %s", version));
+ Slog.i(
+ TAG,
+ String.format(
+ "Successfully pushed rule set to version '%s' from '%s'",
+ version, ruleProvider));
}
+
FrameworkStatsLog.write(
FrameworkStatsLog.INTEGRITY_RULES_PUSHED,
success,
@@ -324,13 +329,12 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
+ getAllowedInstallers(packageInfo));
}
IntegrityCheckResult result = mEvaluationEngine.evaluate(appInstallMetadata);
- if (DEBUG_INTEGRITY_COMPONENT) {
+ if (!result.getMatchedRules().isEmpty() || DEBUG_INTEGRITY_COMPONENT) {
Slog.i(
TAG,
- "Integrity check result: "
- + result.getEffect()
- + " due to "
- + result.getMatchedRules());
+ String.format(
+ "Integrity check of %s result: %s due to %s",
+ packageName, result.getEffect(), result.getMatchedRules()));
}
FrameworkStatsLog.write(
@@ -673,8 +677,10 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
// Obtain the system apps that are whitelisted in config_integrityRuleProviderPackages.
List<String> allowedRuleProviders = getAllowedRuleProviderSystemApps();
if (DEBUG_INTEGRITY_COMPONENT) {
- Slog.i(TAG, String.format(
- "Rule provider system app list contains: %s", allowedRuleProviders));
+ Slog.i(
+ TAG,
+ String.format(
+ "Rule provider system app list contains: %s", allowedRuleProviders));
}
// Identify the package names in the caller list.
@@ -730,9 +736,9 @@ public class AppIntegrityManagerServiceImpl extends IAppIntegrityManager.Stub {
private boolean integrityCheckIncludesRuleProvider() {
return Settings.Global.getInt(
- mContext.getContentResolver(),
- Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER,
- 0)
+ mContext.getContentResolver(),
+ Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER,
+ 0)
== 1;
}
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index bfcbe465a271..9adde24a99e0 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -1586,6 +1586,7 @@ public class LocationManagerService extends ILocationManager.Stub {
}
record.mRequest = locationRequest;
+ record.mReceiver.updateMonitoring(true);
requests.add(locationRequest);
if (!locationRequest.isLowPowerMode()) {
providerRequest.setLowPowerMode(false);
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 9b356f0e8eef..803eb862e0f1 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -1937,7 +1937,8 @@ public class MediaSessionService extends SystemService implements Monitor {
// Context#getPackageName() for getting package name that matches with the PID/UID,
// but it doesn't tell which package has created the MediaController, so useless.
return hasMediaControlPermission(controllerPid, controllerUid)
- || hasEnabledNotificationListener(userId, controllerPackageName);
+ || hasEnabledNotificationListener(
+ userId, controllerPackageName, controllerUid);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -2001,29 +2002,29 @@ public class MediaSessionService extends SystemService implements Monitor {
return resolvedUserId;
}
- private boolean hasEnabledNotificationListener(int resolvedUserId, String packageName)
- throws RemoteException {
- // You may not access another user's content as an enabled listener.
- final int userId = UserHandle.getUserId(resolvedUserId);
- if (resolvedUserId != userId) {
+ private boolean hasEnabledNotificationListener(int callingUserId,
+ String controllerPackageName, int controllerUid) throws RemoteException {
+ int controllerUserId = UserHandle.getUserHandleForUid(controllerUid).getIdentifier();
+ if (callingUserId != controllerUserId) {
+ // Enabled notification listener only works within the same user.
return false;
}
// TODO(jaewan): (Post-P) Propose NotificationManager#hasEnabledNotificationListener(
// String pkgName) to notification team for optimization
final List<ComponentName> enabledNotificationListeners =
- mNotificationManager.getEnabledNotificationListeners(userId);
+ mNotificationManager.getEnabledNotificationListeners(controllerUserId);
if (enabledNotificationListeners != null) {
for (int i = 0; i < enabledNotificationListeners.size(); i++) {
- if (TextUtils.equals(packageName,
+ if (TextUtils.equals(controllerPackageName,
enabledNotificationListeners.get(i).getPackageName())) {
return true;
}
}
}
if (DEBUG) {
- Log.d(TAG, packageName + " (uid=" + resolvedUserId + ") doesn't have an enabled "
- + "notification listener");
+ Log.d(TAG, controllerPackageName + " (uid=" + controllerUid
+ + ") doesn't have an enabled notification listener");
}
return false;
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
index cb1c7e4fd0de..1c79332e9895 100644
--- a/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
+++ b/services/core/java/com/android/server/net/NetworkStatsSubscriptionsMonitor.java
@@ -99,11 +99,16 @@ public class NetworkStatsSubscriptionsMonitor extends
if (match != null) continue;
// Create listener for every newly added sub. Also store subscriberId into it to
- // prevent binder call to telephony when querying RAT.
+ // prevent binder call to telephony when querying RAT. If the subscriberId is empty
+ // for any reason, such as SIM PIN locked, skip registration.
+ // SubscriberId will be unavailable again if 1. modem crashed 2. reboot
+ // 3. re-insert SIM. If that happens, the listeners will be eventually synchronized
+ // with active sub list once all subscriberIds are ready.
final String subscriberId = mTeleManager.getSubscriberId(subId);
if (TextUtils.isEmpty(subscriberId)) {
- Log.wtf(NetworkStatsService.TAG,
- "Empty subscriberId for newly added sub: " + subId);
+ Log.d(NetworkStatsService.TAG, "Empty subscriberId for newly added sub "
+ + subId + ", skip listener registration");
+ continue;
}
final RatTypeListener listener =
new RatTypeListener(mExecutor, this, subId, subscriberId);
@@ -112,6 +117,7 @@ public class NetworkStatsSubscriptionsMonitor extends
// Register listener to the telephony manager that associated with specific sub.
mTeleManager.createForSubscriptionId(subId)
.listen(listener, PhoneStateListener.LISTEN_SERVICE_STATE);
+ Log.d(NetworkStatsService.TAG, "RAT type listener registered for sub " + subId);
}
for (final RatTypeListener listener : new ArrayList<>(mRatListeners)) {
@@ -164,6 +170,7 @@ public class NetworkStatsSubscriptionsMonitor extends
private void handleRemoveRatTypeListener(@NonNull RatTypeListener listener) {
mTeleManager.createForSubscriptionId(listener.mSubId)
.listen(listener, PhoneStateListener.LISTEN_NONE);
+ Log.d(NetworkStatsService.TAG, "RAT type listener unregistered for sub " + listener.mSubId);
mRatListeners.remove(listener);
// Removal of subscriptions doesn't generate RAT changed event, fire it for every
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8dc7b93302a0..5d0981da1906 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1939,6 +1939,13 @@ public class NotificationManagerService extends SystemService {
}
@Override
+ void onConsolidatedPolicyChanged() {
+ Binder.withCleanCallingIdentity(() -> {
+ mRankingHandler.requestSort();
+ });
+ }
+
+ @Override
void onAutomaticRuleStatusChanged(int userId, String pkg, String id, int status) {
Binder.withCleanCallingIdentity(() -> {
Intent intent = new Intent(ACTION_AUTOMATIC_ZEN_RULE_STATUS_CHANGED);
@@ -6238,6 +6245,8 @@ public class NotificationManagerService extends SystemService {
for (NotificationRecord r : enqueued) {
if (r.mUpdateTimeMs > mWhen) {
// At least one enqueue was posted after the cancel, so we're invalid
+ Slog.i(TAG, "notification cancel ignored due to newer enqueued entry"
+ + "key=" + r.getSbn().getKey());
return;
}
}
@@ -7733,6 +7742,13 @@ public class NotificationManagerService extends SystemService {
@VisibleForTesting
void updateUriPermissions(@Nullable NotificationRecord newRecord,
@Nullable NotificationRecord oldRecord, String targetPkg, int targetUserId) {
+ updateUriPermissions(newRecord, oldRecord, targetPkg, targetUserId, false);
+ }
+
+ @VisibleForTesting
+ void updateUriPermissions(@Nullable NotificationRecord newRecord,
+ @Nullable NotificationRecord oldRecord, String targetPkg, int targetUserId,
+ boolean onlyRevokeCurrentTarget) {
final String key = (newRecord != null) ? newRecord.getKey() : oldRecord.getKey();
if (DBG) Slog.d(TAG, key + ": updating permissions");
@@ -7760,7 +7776,9 @@ public class NotificationManagerService extends SystemService {
}
// If we have no Uris to grant, but an existing owner, go destroy it
- if (newUris == null && permissionOwner != null) {
+ // When revoking permissions of a single listener, destroying the owner will revoke
+ // permissions of other listeners who need to keep access.
+ if (newUris == null && permissionOwner != null && !onlyRevokeCurrentTarget) {
destroyPermissionOwner(permissionOwner, UserHandle.getUserId(oldRecord.getUid()), key);
permissionOwner = null;
}
@@ -7783,9 +7801,20 @@ public class NotificationManagerService extends SystemService {
final Uri uri = oldUris.valueAt(i);
if (newUris == null || !newUris.contains(uri)) {
if (DBG) Slog.d(TAG, key + ": revoking " + uri);
- int userId = ContentProvider.getUserIdFromUri(
- uri, UserHandle.getUserId(oldRecord.getUid()));
- revokeUriPermission(permissionOwner, uri, userId);
+ if (onlyRevokeCurrentTarget) {
+ // We're revoking permission from one listener only; other listeners may
+ // still need access because the notification may still exist
+ revokeUriPermission(permissionOwner, uri,
+ UserHandle.getUserId(oldRecord.getUid()), targetPkg, targetUserId);
+ } else {
+ // This is broad to unilaterally revoke permissions to this Uri as granted
+ // by this notification. But this code-path can only be used when the
+ // reason for revoking is that the notification posted again without this
+ // Uri, not when removing an individual listener.
+ revokeUriPermission(permissionOwner, uri,
+ UserHandle.getUserId(oldRecord.getUid()),
+ null, UserHandle.USER_ALL);
+ }
}
}
}
@@ -7814,8 +7843,10 @@ public class NotificationManagerService extends SystemService {
}
}
- private void revokeUriPermission(IBinder owner, Uri uri, int userId) {
+ private void revokeUriPermission(IBinder owner, Uri uri, int sourceUserId, String targetPkg,
+ int targetUserId) {
if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return;
+ int userId = ContentProvider.getUserIdFromUri(uri, sourceUserId);
final long ident = Binder.clearCallingIdentity();
try {
@@ -7823,7 +7854,7 @@ public class NotificationManagerService extends SystemService {
owner,
ContentProvider.getUriWithoutUserId(uri),
Intent.FLAG_GRANT_READ_URI_PERMISSION,
- userId);
+ userId, targetPkg, targetUserId);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -9191,6 +9222,7 @@ public class NotificationManagerService extends SystemService {
final NotificationRankingUpdate update;
synchronized (mNotificationLock) {
update = makeRankingUpdateLocked(info);
+ updateUriPermissionsForActiveNotificationsLocked(info, true);
}
try {
listener.onListenerConnected(update);
@@ -9202,6 +9234,7 @@ public class NotificationManagerService extends SystemService {
@Override
@GuardedBy("mNotificationLock")
protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
+ updateUriPermissionsForActiveNotificationsLocked(removed, false);
if (removeDisabledHints(removed)) {
updateListenerHintsLocked();
updateEffectsSuppressorLocked();
@@ -9268,8 +9301,7 @@ public class NotificationManagerService extends SystemService {
for (final ManagedServiceInfo info : getServices()) {
boolean sbnVisible = isVisibleToListener(sbn, info);
- boolean oldSbnVisible = oldSbn != null ? isVisibleToListener(oldSbn, info)
- : false;
+ boolean oldSbnVisible = (oldSbn != null) && isVisibleToListener(oldSbn, info);
// This notification hasn't been and still isn't visible -> ignore.
if (!oldSbnVisible && !sbnVisible) {
continue;
@@ -9293,13 +9325,8 @@ public class NotificationManagerService extends SystemService {
// This notification became invisible -> remove the old one.
if (oldSbnVisible && !sbnVisible) {
final StatusBarNotification oldSbnLightClone = oldSbn.cloneLight();
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyRemoved(
- info, oldSbnLightClone, update, null, REASON_USER_STOPPED);
- }
- });
+ mHandler.post(() -> notifyRemoved(
+ info, oldSbnLightClone, update, null, REASON_USER_STOPPED));
continue;
}
@@ -9309,12 +9336,7 @@ public class NotificationManagerService extends SystemService {
updateUriPermissions(r, old, info.component.getPackageName(), targetUserId);
final StatusBarNotification sbnToPost = trimCache.ForListener(info);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyPosted(info, sbnToPost, update);
- }
- });
+ mHandler.post(() -> notifyPosted(info, sbnToPost, update));
}
} catch (Exception e) {
Slog.e(TAG, "Could not notify listeners for " + r.getKey(), e);
@@ -9322,6 +9344,46 @@ public class NotificationManagerService extends SystemService {
}
/**
+ * Synchronously grant or revoke permissions to Uris for all active and visible
+ * notifications to just the NotificationListenerService provided.
+ */
+ @GuardedBy("mNotificationLock")
+ private void updateUriPermissionsForActiveNotificationsLocked(
+ ManagedServiceInfo info, boolean grant) {
+ try {
+ for (final NotificationRecord r : mNotificationList) {
+ // When granting permissions, ignore notifications which are invisible.
+ // When revoking permissions, all notifications are invisible, so process all.
+ if (grant && !isVisibleToListener(r.getSbn(), info)) {
+ continue;
+ }
+ // If the notification is hidden, permissions are not required by the listener.
+ if (r.isHidden() && info.targetSdkVersion < Build.VERSION_CODES.P) {
+ continue;
+ }
+ // Grant or revoke access synchronously
+ final int targetUserId = (info.userid == UserHandle.USER_ALL)
+ ? UserHandle.USER_SYSTEM : info.userid;
+ if (grant) {
+ // Grant permissions by passing arguments as if the notification is new.
+ updateUriPermissions(/* newRecord */ r, /* oldRecord */ null,
+ info.component.getPackageName(), targetUserId);
+ } else {
+ // Revoke permissions by passing arguments as if the notification was
+ // removed, but set `onlyRevokeCurrentTarget` to avoid revoking permissions
+ // granted to *other* targets by this notification's URIs.
+ updateUriPermissions(/* newRecord */ null, /* oldRecord */ r,
+ info.component.getPackageName(), targetUserId,
+ /* onlyRevokeCurrentTarget */ true);
+ }
+ }
+ } catch (Exception e) {
+ Slog.e(TAG, "Could not " + (grant ? "grant" : "revoke") + " Uri permissions to "
+ + info.component, e);
+ }
+ }
+
+ /**
* asynchronously notify all listeners about a removed notification
*/
@GuardedBy("mNotificationLock")
@@ -9356,18 +9418,11 @@ public class NotificationManagerService extends SystemService {
final NotificationStats stats = mAssistants.isServiceTokenValidLocked(info.service)
? notificationStats : null;
final NotificationRankingUpdate update = makeRankingUpdateLocked(info);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- notifyRemoved(info, sbnLight, update, stats, reason);
- }
- });
+ mHandler.post(() -> notifyRemoved(info, sbnLight, update, stats, reason));
}
// Revoke access after all listeners have been updated
- mHandler.post(() -> {
- updateUriPermissions(null, r, null, UserHandle.USER_SYSTEM);
- });
+ mHandler.post(() -> updateUriPermissions(null, r, null, UserHandle.USER_SYSTEM));
}
/**
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index c3c2e5e65103..10f77144e022 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -35,6 +35,9 @@ import android.content.pm.parsing.component.ParsedInstrumentation;
import android.content.pm.parsing.component.ParsedIntentInfo;
import android.content.pm.parsing.component.ParsedMainComponent;
import android.content.pm.parsing.component.ParsedProvider;
+import android.os.Handler;
+import android.os.HandlerExecutor;
+import android.os.HandlerThread;
import android.os.Process;
import android.os.Trace;
import android.os.UserHandle;
@@ -48,6 +51,7 @@ import android.util.SparseBooleanArray;
import android.util.SparseSetArray;
import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.server.FgThread;
@@ -61,6 +65,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.StringTokenizer;
+import java.util.concurrent.Executor;
/**
* The entity responsible for filtering visibility between apps based on declarations in their
@@ -96,6 +101,12 @@ public class AppsFilter {
private final SparseSetArray<Integer> mQueriesViaComponent = new SparseSetArray<>();
/**
+ * Executor for running reasonably short background tasks such as building the initial
+ * visibility cache.
+ */
+ private final Executor mBackgroundExecutor;
+
+ /**
* Pending full recompute of mQueriesViaComponent. Occurs when a package adds a new set of
* protected broadcast. This in turn invalidates all prior additions and require a very
* computationally expensive recomputing.
@@ -125,6 +136,8 @@ public class AppsFilter {
private PackageParser.SigningDetails mSystemSigningDetails;
private Set<String> mProtectedBroadcasts = new ArraySet<>();
+ private final Object mCacheLock = new Object();
+
/**
* This structure maps uid -> uid and indicates whether access from the first should be
* filtered to the second. It's essentially a cache of the
@@ -132,6 +145,7 @@ public class AppsFilter {
* NOTE: It can only be relied upon after the system is ready to avoid unnecessary update on
* initial scam and is null until {@link #onSystemReady()} is called.
*/
+ @GuardedBy("mCacheLock")
private volatile SparseArray<SparseBooleanArray> mShouldFilterCache;
@VisibleForTesting(visibility = PRIVATE)
@@ -139,13 +153,15 @@ public class AppsFilter {
FeatureConfig featureConfig,
String[] forceQueryableWhitelist,
boolean systemAppsQueryable,
- @Nullable OverlayReferenceMapper.Provider overlayProvider) {
+ @Nullable OverlayReferenceMapper.Provider overlayProvider,
+ Executor backgroundExecutor) {
mFeatureConfig = featureConfig;
mForceQueryableByDevicePackageNames = forceQueryableWhitelist;
mSystemAppsQueryable = systemAppsQueryable;
mOverlayReferenceMapper = new OverlayReferenceMapper(true /*deferRebuild*/,
overlayProvider);
mStateProvider = stateProvider;
+ mBackgroundExecutor = backgroundExecutor;
}
/**
@@ -337,8 +353,13 @@ public class AppsFilter {
injector.getUserManagerInternal().getUserInfos());
}
};
+ HandlerThread appsFilterThread = new HandlerThread("appsFilter");
+ appsFilterThread.start();
+ Handler appsFilterHandler = new Handler(appsFilterThread.getLooper());
+ Executor executor = new HandlerExecutor(appsFilterHandler);
+
AppsFilter appsFilter = new AppsFilter(stateProvider, featureConfig,
- forcedQueryablePackageNames, forceSystemAppsQueryable, null);
+ forcedQueryablePackageNames, forceSystemAppsQueryable, null, executor);
featureConfig.setAppsFilter(appsFilter);
return appsFilter;
}
@@ -470,29 +491,26 @@ public class AppsFilter {
if (mImplicitlyQueryable.add(recipientUid, visibleUid) && DEBUG_LOGGING) {
Slog.i(TAG, "implicit access granted: " + recipientUid + " -> " + visibleUid);
}
- if (mShouldFilterCache != null) {
- // update the cache in a one-off manner since we've got all the information we need.
- SparseBooleanArray visibleUids = mShouldFilterCache.get(recipientUid);
- if (visibleUids == null) {
- visibleUids = new SparseBooleanArray();
- mShouldFilterCache.put(recipientUid, visibleUids);
+ synchronized (mCacheLock) {
+ if (mShouldFilterCache != null) {
+ // update the cache in a one-off manner since we've got all the information we
+ // need.
+ SparseBooleanArray visibleUids = mShouldFilterCache.get(recipientUid);
+ if (visibleUids == null) {
+ visibleUids = new SparseBooleanArray();
+ mShouldFilterCache.put(recipientUid, visibleUids);
+ }
+ visibleUids.put(visibleUid, false);
}
- visibleUids.put(visibleUid, false);
}
}
}
public void onSystemReady() {
- mStateProvider.runWithState(new StateProvider.CurrentStateCallback() {
- @Override
- public void currentState(ArrayMap<String, PackageSetting> settings,
- UserInfo[] users) {
- mShouldFilterCache = new SparseArray<>(users.length * settings.size());
- }
- });
- mFeatureConfig.onSystemReady();
mOverlayReferenceMapper.rebuildIfDeferred();
- updateEntireShouldFilterCache();
+ mFeatureConfig.onSystemReady();
+
+ updateEntireShouldFilterCacheAsync();
}
/**
@@ -510,10 +528,12 @@ public class AppsFilter {
}
mStateProvider.runWithState((settings, users) -> {
addPackageInternal(newPkgSetting, settings);
- if (mShouldFilterCache != null) {
- updateShouldFilterCacheForPackage(
- null, newPkgSetting, settings, users, settings.size());
- } // else, rebuild entire cache when system is ready
+ synchronized (mCacheLock) {
+ if (mShouldFilterCache != null) {
+ updateShouldFilterCacheForPackage(mShouldFilterCache, null, newPkgSetting,
+ settings, users, settings.size());
+ } // else, rebuild entire cache when system is ready
+ }
});
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -547,9 +567,9 @@ public class AppsFilter {
final boolean newIsForceQueryable =
mForceQueryable.contains(newPkgSetting.appId)
/* shared user that is already force queryable */
- || newPkg.isForceQueryable()
- || newPkgSetting.forceQueryableOverride
+ || newPkgSetting.forceQueryableOverride /* adb override */
|| (newPkgSetting.isSystem() && (mSystemAppsQueryable
+ || newPkg.isForceQueryable()
|| ArrayUtils.contains(mForceQueryableByDevicePackageNames,
newPkg.getPackageName())));
if (newIsForceQueryable
@@ -607,6 +627,7 @@ public class AppsFilter {
mFeatureConfig.updatePackageState(newPkgSetting, false /*removed*/);
}
+ @GuardedBy("mCacheLock")
private void removeAppIdFromVisibilityCache(int appId) {
if (mShouldFilterCache == null) {
return;
@@ -627,31 +648,95 @@ public class AppsFilter {
private void updateEntireShouldFilterCache() {
mStateProvider.runWithState((settings, users) -> {
- mShouldFilterCache.clear();
- for (int i = settings.size() - 1; i >= 0; i--) {
- updateShouldFilterCacheForPackage(
- null /*skipPackage*/, settings.valueAt(i), settings, users, i);
+ SparseArray<SparseBooleanArray> cache =
+ updateEntireShouldFilterCacheInner(settings, users);
+ synchronized (mCacheLock) {
+ mShouldFilterCache = cache;
}
});
}
- public void onUsersChanged() {
- if (mShouldFilterCache != null) {
- updateEntireShouldFilterCache();
+ private SparseArray<SparseBooleanArray> updateEntireShouldFilterCacheInner(
+ ArrayMap<String, PackageSetting> settings, UserInfo[] users) {
+ SparseArray<SparseBooleanArray> cache =
+ new SparseArray<>(users.length * settings.size());
+ for (int i = settings.size() - 1; i >= 0; i--) {
+ updateShouldFilterCacheForPackage(cache,
+ null /*skipPackage*/, settings.valueAt(i), settings, users, i);
}
+ return cache;
}
- private void updateShouldFilterCacheForPackage(String packageName) {
- mStateProvider.runWithState((settings, users) -> {
- updateShouldFilterCacheForPackage(null /* skipPackage */, settings.get(packageName),
- settings, users, settings.size() /*maxIndex*/);
+ private void updateEntireShouldFilterCacheAsync() {
+ mBackgroundExecutor.execute(() -> {
+ final ArrayMap<String, PackageSetting> settingsCopy = new ArrayMap<>();
+ final ArrayMap<String, AndroidPackage> packagesCache = new ArrayMap<>();
+ final UserInfo[][] usersRef = new UserInfo[1][];
+ mStateProvider.runWithState((settings, users) -> {
+ packagesCache.ensureCapacity(settings.size());
+ settingsCopy.putAll(settings);
+ usersRef[0] = users;
+ // store away the references to the immutable packages, since settings are retained
+ // during updates.
+ for (int i = 0, max = settings.size(); i < max; i++) {
+ final AndroidPackage pkg = settings.valueAt(i).pkg;
+ packagesCache.put(settings.keyAt(i), pkg);
+ }
+ });
+ SparseArray<SparseBooleanArray> cache =
+ updateEntireShouldFilterCacheInner(settingsCopy, usersRef[0]);
+ boolean[] changed = new boolean[1];
+ // We have a cache, let's make sure the world hasn't changed out from under us.
+ mStateProvider.runWithState((settings, users) -> {
+ if (settings.size() != settingsCopy.size()) {
+ changed[0] = true;
+ return;
+ }
+ for (int i = 0, max = settings.size(); i < max; i++) {
+ final AndroidPackage pkg = settings.valueAt(i).pkg;
+ if (!Objects.equals(pkg, packagesCache.get(settings.keyAt(i)))) {
+ changed[0] = true;
+ return;
+ }
+ }
+ });
+ if (changed[0]) {
+ // Something has changed, just update the cache inline with the lock held
+ updateEntireShouldFilterCache();
+ if (DEBUG_LOGGING) {
+ Slog.i(TAG, "Rebuilding cache with lock due to package change.");
+ }
+ } else {
+ synchronized (mCacheLock) {
+ mShouldFilterCache = cache;
+ }
+ }
});
+ }
+
+ public void onUsersChanged() {
+ synchronized (mCacheLock) {
+ if (mShouldFilterCache != null) {
+ updateEntireShouldFilterCache();
+ }
+ }
+ }
+ private void updateShouldFilterCacheForPackage(String packageName) {
+ synchronized (mCacheLock) {
+ if (mShouldFilterCache != null) {
+ mStateProvider.runWithState((settings, users) -> {
+ updateShouldFilterCacheForPackage(mShouldFilterCache, null /* skipPackage */,
+ settings.get(packageName), settings, users,
+ settings.size() /*maxIndex*/);
+ });
+ }
+ }
}
- private void updateShouldFilterCacheForPackage(@Nullable String skipPackageName,
- PackageSetting subjectSetting, ArrayMap<String, PackageSetting> allSettings,
- UserInfo[] allUsers, int maxIndex) {
+ private void updateShouldFilterCacheForPackage(SparseArray<SparseBooleanArray> cache,
+ @Nullable String skipPackageName, PackageSetting subjectSetting, ArrayMap<String,
+ PackageSetting> allSettings, UserInfo[] allUsers, int maxIndex) {
for (int i = Math.min(maxIndex, allSettings.size() - 1); i >= 0; i--) {
PackageSetting otherSetting = allSettings.valueAt(i);
if (subjectSetting.appId == otherSetting.appId) {
@@ -668,17 +753,17 @@ public class AppsFilter {
for (int ou = 0; ou < userCount; ou++) {
int otherUser = allUsers[ou].id;
int subjectUid = UserHandle.getUid(subjectUser, subjectSetting.appId);
- if (!mShouldFilterCache.contains(subjectUid)) {
- mShouldFilterCache.put(subjectUid, new SparseBooleanArray(appxUidCount));
+ if (!cache.contains(subjectUid)) {
+ cache.put(subjectUid, new SparseBooleanArray(appxUidCount));
}
int otherUid = UserHandle.getUid(otherUser, otherSetting.appId);
- if (!mShouldFilterCache.contains(otherUid)) {
- mShouldFilterCache.put(otherUid, new SparseBooleanArray(appxUidCount));
+ if (!cache.contains(otherUid)) {
+ cache.put(otherUid, new SparseBooleanArray(appxUidCount));
}
- mShouldFilterCache.get(subjectUid).put(otherUid,
+ cache.get(subjectUid).put(otherUid,
shouldFilterApplicationInternal(
subjectUid, subjectSetting, otherSetting, otherUser));
- mShouldFilterCache.get(otherUid).put(subjectUid,
+ cache.get(otherUid).put(subjectUid,
shouldFilterApplicationInternal(
otherUid, otherSetting, subjectSetting, subjectUser));
}
@@ -712,7 +797,8 @@ public class AppsFilter {
* This method recomputes all component / intent-based visibility and is intended to match the
* relevant logic of {@link #addPackageInternal(PackageSetting, ArrayMap)}
*/
- private void recomputeComponentVisibility(ArrayMap<String, PackageSetting> existingSettings) {
+ private void recomputeComponentVisibility(
+ ArrayMap<String, PackageSetting> existingSettings) {
mQueriesViaComponent.clear();
for (int i = existingSettings.size() - 1; i >= 0; i--) {
PackageSetting setting = existingSettings.valueAt(i);
@@ -854,15 +940,17 @@ public class AppsFilter {
}
}
- removeAppIdFromVisibilityCache(setting.appId);
- if (mShouldFilterCache != null && setting.sharedUser != null) {
- for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) {
- PackageSetting siblingSetting = setting.sharedUser.packages.valueAt(i);
- if (siblingSetting == setting) {
- continue;
+ synchronized (mCacheLock) {
+ removeAppIdFromVisibilityCache(setting.appId);
+ if (mShouldFilterCache != null && setting.sharedUser != null) {
+ for (int i = setting.sharedUser.packages.size() - 1; i >= 0; i--) {
+ PackageSetting siblingSetting = setting.sharedUser.packages.valueAt(i);
+ if (siblingSetting == setting) {
+ continue;
+ }
+ updateShouldFilterCacheForPackage(mShouldFilterCache, setting.name,
+ siblingSetting, settings, users, settings.size());
}
- updateShouldFilterCacheForPackage(
- setting.name, siblingSetting, settings, users, settings.size());
}
}
});
@@ -888,26 +976,29 @@ public class AppsFilter {
|| callingAppId == targetPkgSetting.appId) {
return false;
}
- if (mShouldFilterCache != null) { // use cache
- SparseBooleanArray shouldFilterTargets = mShouldFilterCache.get(callingUid);
- final int targetUid = UserHandle.getUid(userId, targetPkgSetting.appId);
- if (shouldFilterTargets == null) {
- Slog.wtf(TAG, "Encountered calling uid with no cached rules: " + callingUid);
- return true;
- }
- int indexOfTargetUid = shouldFilterTargets.indexOfKey(targetUid);
- if (indexOfTargetUid < 0) {
- Slog.w(TAG, "Encountered calling -> target with no cached rules: "
- + callingUid + " -> " + targetUid);
- return true;
- }
- if (!shouldFilterTargets.valueAt(indexOfTargetUid)) {
- return false;
- }
- } else {
- if (!shouldFilterApplicationInternal(
- callingUid, callingSetting, targetPkgSetting, userId)) {
- return false;
+ synchronized (mCacheLock) {
+ if (mShouldFilterCache != null) { // use cache
+ SparseBooleanArray shouldFilterTargets = mShouldFilterCache.get(callingUid);
+ final int targetUid = UserHandle.getUid(userId, targetPkgSetting.appId);
+ if (shouldFilterTargets == null) {
+ Slog.wtf(TAG, "Encountered calling uid with no cached rules: "
+ + callingUid);
+ return true;
+ }
+ int indexOfTargetUid = shouldFilterTargets.indexOfKey(targetUid);
+ if (indexOfTargetUid < 0) {
+ Slog.w(TAG, "Encountered calling -> target with no cached rules: "
+ + callingUid + " -> " + targetUid);
+ return true;
+ }
+ if (!shouldFilterTargets.valueAt(indexOfTargetUid)) {
+ return false;
+ }
+ } else {
+ if (!shouldFilterApplicationInternal(
+ callingUid, callingSetting, targetPkgSetting, userId)) {
+ return false;
+ }
}
}
if (DEBUG_LOGGING || mFeatureConfig.isLoggingEnabled(callingAppId)) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 994cec2b1e59..ea53132ae409 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -267,6 +267,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
/** Uid of the creator of this session. */
private final int mOriginalInstallerUid;
+ /** Package name of the app that created the installation session. */
+ private final String mOriginalInstallerPackageName;
+
/** Uid of the owner of the installer session */
@GuardedBy("mLock")
private int mInstallerUid;
@@ -556,6 +559,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mOriginalInstallerUid = installerUid;
mInstallerUid = installerUid;
mInstallSource = Objects.requireNonNull(installSource);
+ mOriginalInstallerPackageName = mInstallSource.installerPackageName;
this.params = params;
this.createdMillis = createdMillis;
this.updatedMillis = createdMillis;
@@ -1666,11 +1670,6 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
throw new IllegalArgumentException("Package is not valid", e);
}
- if (!mPackageName.equals(mInstallSource.installerPackageName)) {
- throw new SecurityException("Can only transfer sessions that update the original "
- + "installer");
- }
-
mInstallerUid = newOwnerAppInfo.uid;
mInstallSource = InstallSource.create(packageName, null, packageName);
}
@@ -2157,6 +2156,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ if (mInstallerUid != mOriginalInstallerUid) {
+ // Session has been transferred, check package name.
+ if (TextUtils.isEmpty(mPackageName) || !mPackageName.equals(
+ mOriginalInstallerPackageName)) {
+ throw new PackageManagerException(PackageManager.INSTALL_FAILED_PACKAGE_CHANGED,
+ "Can only transfer sessions that update the original installer");
+ }
+ }
+
if (params.mode == SessionParams.MODE_FULL_INSTALL) {
// Full installs must include a base package
if (!stagedSplits.contains(null)) {
@@ -3182,6 +3190,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
pw.printPair("userId", userId);
pw.printPair("mOriginalInstallerUid", mOriginalInstallerUid);
+ pw.printPair("mOriginalInstallerPackageName", mOriginalInstallerPackageName);
pw.printPair("installerPackageName", mInstallSource.installerPackageName);
pw.printPair("installInitiatingPackageName", mInstallSource.initiatingPackageName);
pw.printPair("installOriginatingPackageName", mInstallSource.originatingPackageName);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index eefad1c8eed2..daca0b34ec2a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2376,9 +2376,12 @@ public class PackageManagerService extends IPackageManager.Stub
final int callingUserId = UserHandle.getUserId(callingUid);
for (String packageName : packages) {
- PackageSetting setting = mSettings.mPackages.get(packageName);
- if (setting != null
- && !shouldFilterApplicationLocked(setting, callingUid, callingUserId)) {
+ final boolean filterApp;
+ synchronized (mLock) {
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
+ filterApp = shouldFilterApplicationLocked(ps, callingUid, callingUserId);
+ }
+ if (!filterApp) {
notifyInstallObserver(packageName);
}
}
@@ -2988,7 +2991,10 @@ public class PackageManagerService extends IPackageManager.Stub
t.traceEnd();
t.traceBegin("read user settings");
- mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers(false));
+ mFirstBoot = !mSettings.readLPw(mInjector.getUserManagerInternal().getUsers(
+ /* excludePartial= */ true,
+ /* excludeDying= */ false,
+ /* excludePreCreated= */ false));
t.traceEnd();
// Clean up orphaned packages for which the code path doesn't exist
@@ -4198,13 +4204,9 @@ public class PackageManagerService extends IPackageManager.Stub
Iterator<ResolveInfo> iter = matches.iterator();
while (iter.hasNext()) {
final ResolveInfo rInfo = iter.next();
- final PackageSetting ps = mSettings.mPackages.get(rInfo.activityInfo.packageName);
- if (ps != null) {
- final PermissionsState permissionsState = ps.getPermissionsState();
- if (permissionsState.hasPermission(Manifest.permission.INSTALL_PACKAGES, 0)
- || Build.IS_ENG) {
- continue;
- }
+ if (checkPermission(Manifest.permission.INSTALL_PACKAGES,
+ rInfo.activityInfo.packageName, 0) == PERMISSION_GRANTED || Build.IS_ENG) {
+ continue;
}
iter.remove();
}
@@ -4380,8 +4382,24 @@ public class PackageManagerService extends IPackageManager.Stub
final int[] gids = (flags & PackageManager.GET_GIDS) == 0
? EMPTY_INT_ARRAY : permissionsState.computeGids(userId);
// Compute granted permissions only if package has requested permissions
- final Set<String> permissions = ArrayUtils.isEmpty(p.getRequestedPermissions())
+ Set<String> permissions = ArrayUtils.isEmpty(p.getRequestedPermissions())
? Collections.emptySet() : permissionsState.getPermissions(userId);
+ if (state.instantApp) {
+ permissions = new ArraySet<>(permissions);
+ permissions.removeIf(permissionName -> {
+ BasePermission permission = mPermissionManager.getPermissionTEMP(
+ permissionName);
+ if (permission == null) {
+ return true;
+ }
+ if (!permission.isInstant()) {
+ EventLog.writeEvent(0x534e4554, "140256621", UserHandle.getUid(userId,
+ ps.appId), permissionName);
+ return true;
+ }
+ return false;
+ });
+ }
PackageInfo packageInfo = PackageInfoUtils.generate(p, gids, flags,
ps.firstInstallTime, ps.lastUpdateTime, permissions, state, userId, ps);
@@ -8579,10 +8597,9 @@ public class PackageManagerService extends IPackageManager.Stub
private void addPackageHoldingPermissions(ArrayList<PackageInfo> list, PackageSetting ps,
String[] permissions, boolean[] tmp, int flags, int userId) {
int numMatch = 0;
- final PermissionsState permissionsState = ps.getPermissionsState();
for (int i=0; i<permissions.length; i++) {
final String permission = permissions[i];
- if (permissionsState.hasPermission(permission, userId)) {
+ if (checkPermission(permission, ps.name, userId) == PERMISSION_GRANTED) {
tmp[i] = true;
numMatch++;
} else {
@@ -8914,10 +8931,10 @@ public class PackageManagerService extends IPackageManager.Stub
if (providerInfo == null) {
return null;
}
- if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) {
- return null;
- }
synchronized (mLock) {
+ if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) {
+ return null;
+ }
final PackageSetting ps = mSettings.mPackages.get(providerInfo.packageName);
final ComponentName component =
new ComponentName(providerInfo.packageName, providerInfo.name);
@@ -9004,9 +9021,11 @@ public class PackageManagerService extends IPackageManager.Stub
String targetPackage, int flags) {
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
- final PackageSetting ps = mSettings.mPackages.get(targetPackage);
- if (shouldFilterApplicationLocked(ps, callingUid, callingUserId)) {
- return ParceledListSlice.emptyList();
+ synchronized (mLock) {
+ final PackageSetting ps = mSettings.getPackageLPr(targetPackage);
+ if (shouldFilterApplicationLocked(ps, callingUid, callingUserId)) {
+ return ParceledListSlice.emptyList();
+ }
}
return new ParceledListSlice<>(queryInstrumentationInternal(targetPackage, flags,
callingUserId));
@@ -14501,7 +14520,7 @@ public class PackageManagerService extends IPackageManager.Stub
final PackageSetting ps;
int appId = -1;
long ceDataInode = -1;
- synchronized (mSettings) {
+ synchronized (mLock) {
ps = mSettings.getPackageLPr(packageName);
if (ps != null) {
appId = ps.appId;
@@ -19185,6 +19204,14 @@ public class PackageManagerService extends IPackageManager.Stub
final int flags = action.flags;
final boolean systemApp = isSystemApp(ps);
+ // We need to get the permission state before package state is (potentially) destroyed.
+ final SparseBooleanArray hadSuspendAppsPermission = new SparseBooleanArray();
+ // allUserHandles could be null, so call mUserManager.getUserIds() directly which is cached anyway.
+ for (int userId : mUserManager.getUserIds()) {
+ hadSuspendAppsPermission.put(userId, checkPermission(Manifest.permission.SUSPEND_APPS,
+ packageName, userId) == PERMISSION_GRANTED);
+ }
+
final int userId = user == null ? UserHandle.USER_ALL : user.getIdentifier();
if ((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)
@@ -19251,8 +19278,7 @@ public class PackageManagerService extends IPackageManager.Stub
affectedUserIds = resolveUserIds(userId);
}
for (final int affectedUserId : affectedUserIds) {
- if (ps.getPermissionsState().hasPermission(Manifest.permission.SUSPEND_APPS,
- affectedUserId)) {
+ if (hadSuspendAppsPermission.get(affectedUserId)) {
unsuspendForSuspendingPackage(packageName, affectedUserId);
removeAllDistractingPackageRestrictions(affectedUserId);
}
@@ -19356,9 +19382,11 @@ public class PackageManagerService extends IPackageManager.Stub
mPermissionManager.enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, false /* checkShell */, "clear application data");
- final PackageSetting ps = mSettings.getPackageLPr(packageName);
- final boolean filterApp =
- (ps != null && shouldFilterApplicationLocked(ps, callingUid, userId));
+ final boolean filterApp;
+ synchronized (mLock) {
+ final PackageSetting ps = mSettings.getPackageLPr(packageName);
+ filterApp = shouldFilterApplicationLocked(ps, callingUid, userId);
+ }
if (!filterApp && mProtectedPackages.isPackageDataProtected(userId, packageName)) {
throw new SecurityException("Cannot clear data for a protected package: "
+ packageName);
@@ -19638,11 +19666,13 @@ public class PackageManagerService extends IPackageManager.Stub
if (mContext.checkCallingOrSelfPermission(
android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
!= PackageManager.PERMISSION_GRANTED) {
- if (getUidTargetSdkVersionLockedLPr(callingUid)
- < Build.VERSION_CODES.FROYO) {
- Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
- + callingUid);
- return;
+ synchronized (mLock) {
+ if (getUidTargetSdkVersionLockedLPr(callingUid)
+ < Build.VERSION_CODES.FROYO) {
+ Slog.w(TAG, "Ignoring addPreferredActivity() from uid "
+ + callingUid);
+ return;
+ }
}
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
@@ -19814,8 +19844,9 @@ public class PackageManagerService extends IPackageManager.Stub
/** This method takes a specific user id as well as UserHandle.USER_ALL. */
private void clearPackagePreferredActivities(String packageName, int userId) {
final SparseBooleanArray changedUsers = new SparseBooleanArray();
-
- clearPackagePreferredActivitiesLPw(packageName, changedUsers, userId);
+ synchronized (mLock) {
+ clearPackagePreferredActivitiesLPw(packageName, changedUsers, userId);
+ }
if (changedUsers.size() > 0) {
updateDefaultHomeNotLocked(changedUsers);
postPreferredActivityChangedBroadcast(userId);
@@ -19937,7 +19968,9 @@ public class PackageManagerService extends IPackageManager.Stub
// writer
try {
final SparseBooleanArray changedUsers = new SparseBooleanArray();
- clearPackagePreferredActivitiesLPw(null, changedUsers, userId);
+ synchronized (mLock) {
+ clearPackagePreferredActivitiesLPw(null, changedUsers, userId);
+ }
if (changedUsers.size() > 0) {
postPreferredActivityChangedBroadcast(userId);
}
@@ -20942,15 +20975,19 @@ public class PackageManagerService extends IPackageManager.Stub
// Limit who can change which apps
if (!UserHandle.isSameApp(callingUid, pkgSetting.appId)) {
// Don't allow apps that don't have permission to modify other apps
- if (!allowedByPermission
- || shouldFilterApplicationLocked(pkgSetting, callingUid, userId)) {
+ final boolean filterApp;
+ synchronized (mLock) {
+ filterApp = (!allowedByPermission
+ || shouldFilterApplicationLocked(pkgSetting, callingUid, userId));
+ }
+ if (filterApp) {
throw new SecurityException(
"Attempt to change component state; "
- + "pid=" + Binder.getCallingPid()
- + ", uid=" + callingUid
- + (className == null
+ + "pid=" + Binder.getCallingPid()
+ + ", uid=" + callingUid
+ + (className == null
? ", package=" + packageName
- : ", component=" + packageName + "/" + className));
+ : ", component=" + packageName + "/" + className));
}
// Don't allow changing protected packages.
if (mProtectedPackages.isPackageStateProtected(userId, packageName)) {
@@ -21017,8 +21054,8 @@ public class PackageManagerService extends IPackageManager.Stub
pkgSetting.setEnabled(newState, userId, callingPackage);
if ((newState == COMPONENT_ENABLED_STATE_DISABLED_USER
|| newState == COMPONENT_ENABLED_STATE_DISABLED)
- && pkgSetting.getPermissionsState().hasPermission(
- Manifest.permission.SUSPEND_APPS, userId)) {
+ && checkPermission(Manifest.permission.SUSPEND_APPS, packageName, userId)
+ == PERMISSION_GRANTED) {
// This app should not generally be allowed to get disabled by the UI, but if it
// ever does, we don't want to end up with some of the user's apps permanently
// suspended.
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index a0feb94fd3fc..aeea2514d0a4 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -1613,6 +1613,7 @@ public final class Settings {
return;
}
str = new FileInputStream(userPackagesStateFile);
+ if (DEBUG_MU) Log.i(TAG, "Reading " + userPackagesStateFile);
}
final XmlPullParser parser = Xml.newPullParser();
parser.setInput(str, StandardCharsets.UTF_8.name());
@@ -2057,9 +2058,13 @@ public final class Settings {
serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS);
+ if (DEBUG_MU) Log.i(TAG, "Writing " + userPackagesStateFile);
for (final PackageSetting pkg : mPackages.values()) {
final PackageUserState ustate = pkg.readUserState(userId);
- if (DEBUG_MU) Log.i(TAG, " pkg=" + pkg.name + ", state=" + ustate.enabled);
+ if (DEBUG_MU) {
+ Log.i(TAG, " pkg=" + pkg.name + ", installed=" + ustate.installed
+ + ", state=" + ustate.enabled);
+ }
serializer.startTag(null, TAG_PACKAGE);
serializer.attribute(null, ATTR_NAME, pkg.name);
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 5b1c0fdb8249..600357b7697f 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -743,7 +743,6 @@ public class StagingManager {
PackageInstaller.SessionParams params = originalSession.params.copy();
params.isStaged = false;
params.installFlags |= PackageManager.INSTALL_STAGED;
- // TODO(b/129744602): use the userid from the original session.
if (preReboot) {
params.installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
params.installFlags |= PackageManager.INSTALL_DRY_RUN;
@@ -753,7 +752,7 @@ public class StagingManager {
try {
int apkSessionId = mPi.createSession(
params, originalSession.getInstallerPackageName(),
- 0 /* UserHandle.SYSTEM */);
+ originalSession.userId);
PackageInstallerSession apkSession = mPi.getSession(apkSessionId);
apkSession.open();
for (int i = 0, size = apkFilePaths.size(); i < size; i++) {
@@ -811,10 +810,9 @@ public class StagingManager {
if (preReboot) {
params.installFlags &= ~PackageManager.INSTALL_ENABLE_ROLLBACK;
}
- // TODO(b/129744602): use the userid from the original session.
final int apkParentSessionId = mPi.createSession(
params, session.getInstallerPackageName(),
- 0 /* UserHandle.SYSTEM */);
+ session.userId);
final PackageInstallerSession apkParentSession = mPi.getSession(apkParentSessionId);
try {
apkParentSession.open();
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 27924a68ff48..f5d7d9eda1ba 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -114,7 +114,6 @@ import com.android.server.SystemService;
import com.android.server.am.UserState;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.utils.TimingsTraceAndSlog;
-import com.android.server.wm.ActivityTaskManagerInternal;
import libcore.io.IoUtils;
@@ -134,6 +133,7 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -173,6 +173,7 @@ public class UserManagerService extends IUserManager.Stub {
private static final String ATTR_NEXT_SERIAL_NO = "nextSerialNumber";
private static final String ATTR_PARTIAL = "partial";
private static final String ATTR_PRE_CREATED = "preCreated";
+ private static final String ATTR_CONVERTED_FROM_PRE_CREATED = "convertedFromPreCreated";
private static final String ATTR_GUEST_TO_REMOVE = "guestToRemove";
private static final String ATTR_USER_VERSION = "version";
private static final String ATTR_PROFILE_GROUP_ID = "profileGroupId";
@@ -406,6 +407,10 @@ public class UserManagerService extends IUserManager.Stub {
@GuardedBy("mUsersLock")
private int[] mUserIds;
+
+ @GuardedBy("mUsersLock")
+ private int[] mUserIdsIncludingPreCreated;
+
@GuardedBy("mPackagesLock")
private int mNextSerialNumber;
private int mUserVersion = 0;
@@ -2480,16 +2485,35 @@ public class UserManagerService extends IUserManager.Stub {
}
/**
- * Returns an array of user ids. This array is cached here for quick access, so do not modify or
- * cache it elsewhere.
+ * Returns an array of user ids.
+ *
+ * <p>This array is cached here for quick access, so do not modify or cache it elsewhere.
+ *
* @return the array of user ids.
*/
- public int[] getUserIds() {
+ public @NonNull int[] getUserIds() {
synchronized (mUsersLock) {
return mUserIds;
}
}
+ /**
+ * Returns an array of user ids, including pre-created users.
+ *
+ * <p>This method should only used for the specific cases that need to handle pre-created users;
+ * most callers should call {@link #getUserIds()} instead.
+ *
+ * <p>This array is cached here for quick access, so do not modify or
+ * cache it elsewhere.
+ *
+ * @return the array of user ids.
+ */
+ public @NonNull int[] getUserIdsIncludingPreCreated() {
+ synchronized (mUsersLock) {
+ return mUserIdsIncludingPreCreated;
+ }
+ }
+
@GuardedBy({"mRestrictionsLock", "mPackagesLock"})
private void readUserListLP() {
if (!mUserListFile.exists()) {
@@ -2873,6 +2897,9 @@ public class UserManagerService extends IUserManager.Stub {
if (userInfo.preCreated) {
serializer.attribute(null, ATTR_PRE_CREATED, "true");
}
+ if (userInfo.convertedFromPreCreated) {
+ serializer.attribute(null, ATTR_CONVERTED_FROM_PRE_CREATED, "true");
+ }
if (userInfo.guestToRemove) {
serializer.attribute(null, ATTR_GUEST_TO_REMOVE, "true");
}
@@ -3030,6 +3057,7 @@ public class UserManagerService extends IUserManager.Stub {
int restrictedProfileParentId = UserInfo.NO_PROFILE_GROUP_ID;
boolean partial = false;
boolean preCreated = false;
+ boolean converted = false;
boolean guestToRemove = false;
boolean persistSeedData = false;
String seedAccountName = null;
@@ -3081,6 +3109,10 @@ public class UserManagerService extends IUserManager.Stub {
if ("true".equals(valueString)) {
preCreated = true;
}
+ valueString = parser.getAttributeValue(null, ATTR_CONVERTED_FROM_PRE_CREATED);
+ if ("true".equals(valueString)) {
+ converted = true;
+ }
valueString = parser.getAttributeValue(null, ATTR_GUEST_TO_REMOVE);
if ("true".equals(valueString)) {
guestToRemove = true;
@@ -3138,6 +3170,7 @@ public class UserManagerService extends IUserManager.Stub {
userInfo.lastLoggedInFingerprint = lastLoggedInFingerprint;
userInfo.partial = partial;
userInfo.preCreated = preCreated;
+ userInfo.convertedFromPreCreated = converted;
userInfo.guestToRemove = guestToRemove;
userInfo.profileGroupId = profileGroupId;
userInfo.profileBadge = profileBadge;
@@ -3584,6 +3617,7 @@ public class UserManagerService extends IUserManager.Stub {
preCreatedUser.name = name;
preCreatedUser.flags = newFlags;
preCreatedUser.preCreated = false;
+ preCreatedUser.convertedFromPreCreated = true;
preCreatedUser.creationTime = getCreationTime();
synchronized (mPackagesLock) {
@@ -4327,23 +4361,43 @@ public class UserManagerService extends IUserManager.Stub {
*/
private void updateUserIds() {
int num = 0;
+ int numIncludingPreCreated = 0;
synchronized (mUsersLock) {
final int userSize = mUsers.size();
for (int i = 0; i < userSize; i++) {
- UserInfo userInfo = mUsers.valueAt(i).info;
- if (!userInfo.partial && !userInfo.preCreated) {
- num++;
+ final UserInfo userInfo = mUsers.valueAt(i).info;
+ if (!userInfo.partial) {
+ numIncludingPreCreated++;
+ if (!userInfo.preCreated) {
+ num++;
+ }
}
}
+ if (DBG) {
+ Slog.d(LOG_TAG, "updateUserIds(): numberUsers= " + num
+ + " includingPreCreated=" + numIncludingPreCreated);
+ }
final int[] newUsers = new int[num];
+ final int[] newUsersIncludingPreCreated = new int[numIncludingPreCreated];
+
int n = 0;
+ int nIncludingPreCreated = 0;
for (int i = 0; i < userSize; i++) {
- UserInfo userInfo = mUsers.valueAt(i).info;
- if (!userInfo.partial && !userInfo.preCreated) {
- newUsers[n++] = mUsers.keyAt(i);
+ final UserInfo userInfo = mUsers.valueAt(i).info;
+ if (!userInfo.partial) {
+ final int userId = mUsers.keyAt(i);
+ newUsersIncludingPreCreated[nIncludingPreCreated++] = userId;
+ if (!userInfo.preCreated) {
+ newUsers[n++] = userId;
+ }
}
}
mUserIds = newUsers;
+ mUserIdsIncludingPreCreated = newUsersIncludingPreCreated;
+ if (DBG) {
+ Slog.d(LOG_TAG, "updateUserIds(): userIds= " + Arrays.toString(mUserIds)
+ + " includingPreCreated=" + Arrays.toString(mUserIdsIncludingPreCreated));
+ }
}
}
@@ -4626,6 +4680,7 @@ public class UserManagerService extends IUserManager.Stub {
running ? " (running)" : "",
user.partial ? " (partial)" : "",
user.preCreated ? " (pre-created)" : "",
+ user.convertedFromPreCreated ? " (converted)" : "",
current ? " (current)" : "");
} else {
// NOTE: the standard "list users" command is used by integration tests and
@@ -4710,6 +4765,9 @@ public class UserManagerService extends IUserManager.Stub {
if (userInfo.preCreated) {
pw.print(" <pre-created>");
}
+ if (userInfo.convertedFromPreCreated) {
+ pw.print(" <converted>");
+ }
pw.println();
pw.print(" Type: "); pw.println(userInfo.userType);
pw.print(" Flags: "); pw.print(userInfo.flags); pw.print(" (");
@@ -4791,6 +4849,13 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mUserStates) {
pw.println(" Started users state: " + mUserStates);
}
+ synchronized (mUsersLock) {
+ pw.print(" Cached user IDs: ");
+ pw.println(Arrays.toString(mUserIds));
+ pw.print(" Cached user IDs (including pre-created): ");
+ pw.println(Arrays.toString(mUserIdsIncludingPreCreated));
+ }
+
} // synchronized (mPackagesLock)
// Dump some capabilities
@@ -5052,8 +5117,14 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
- return UserManagerService.this.getUsersInternal(/*excludePartial= */ true,
- excludeDying, /* excludePreCreated= */ true);
+ return getUsers(/*excludePartial= */ true, excludeDying, /* excludePreCreated= */ true);
+ }
+
+ @Override
+ public @NonNull List<UserInfo> getUsers(boolean excludePartial, boolean excludeDying,
+ boolean excludePreCreated) {
+ return UserManagerService.this.getUsersInternal(excludePartial, excludeDying,
+ excludePreCreated);
}
@Override
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index a4e8b1c01620..66d8b5974261 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -83,7 +83,6 @@ import android.content.pm.PackageParser;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
-import android.content.pm.UserInfo;
import android.content.pm.parsing.component.ParsedPermission;
import android.content.pm.parsing.component.ParsedPermissionGroup;
import android.content.pm.permission.SplitPermissionInfoParcelable;
@@ -121,7 +120,6 @@ import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
-import android.util.TimingsTraceLog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
@@ -2605,13 +2603,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int N = pkg.getRequestedPermissions().size();
for (int i = 0; i < N; i++) {
final String permName = pkg.getRequestedPermissions().get(i);
+ final String friendlyName = pkg.getPackageName() + "(" + pkg.getUid() + ")";
final BasePermission bp = mSettings.getPermissionLocked(permName);
final boolean appSupportsRuntimePermissions =
pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M;
String upgradedActivityRecognitionPermission = null;
-
if (DEBUG_INSTALL && bp != null) {
- Log.i(TAG, "Package " + pkg.getPackageName()
+ Log.i(TAG, "Package " + friendlyName
+ " checking " + permName + ": " + bp);
}
@@ -2620,7 +2618,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
pkg.getPackageName())) {
if (DEBUG_PERMISSIONS) {
Slog.i(TAG, "Unknown permission " + permName
- + " in package " + pkg.getPackageName());
+ + " in package " + friendlyName);
}
}
continue;
@@ -2636,7 +2634,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
newImplicitPermissions.add(permName);
if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, permName + " is newly added for " + pkg.getPackageName());
+ Slog.i(TAG, permName + " is newly added for " + friendlyName);
}
} else {
// Special case for Activity Recognition permission. Even if AR permission
@@ -2658,8 +2656,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
newImplicitPermissions.add(permName);
if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, permName + " is newly added for "
- + pkg.getPackageName());
+ Slog.i(TAG, permName + " is newly added for " + friendlyName);
}
break;
}
@@ -2673,7 +2670,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// if (/*pkg.isInstantApp()*/ false && !bp.isInstant()) {
// if (DEBUG_PERMISSIONS) {
// Log.i(TAG, "Denying non-ephemeral permission " + bp.getName()
-// + " for package " + pkg.getPackageName());
+// + " for package " + friendlyName);
// }
// continue;
// }
@@ -2681,7 +2678,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (bp.isRuntimeOnly() && !appSupportsRuntimePermissions) {
if (DEBUG_PERMISSIONS) {
Log.i(TAG, "Denying runtime-only permission " + bp.getName()
- + " for package " + pkg.getPackageName());
+ + " for package " + friendlyName);
}
continue;
}
@@ -2718,7 +2715,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (DEBUG_PERMISSIONS) {
Slog.i(TAG, "Considering granting permission " + perm + " to package "
- + pkg.getPackageName());
+ + friendlyName);
}
if (grant != GRANT_DENIED) {
@@ -3007,7 +3004,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|| packageOfInterest.equals(pkg.getPackageName())) {
if (DEBUG_PERMISSIONS) {
Slog.i(TAG, "Not granting permission " + perm
- + " to package " + pkg.getPackageName()
+ + " to package " + friendlyName
+ " because it was previously installed without");
}
}
@@ -3022,7 +3019,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
changedInstallPermission = true;
if (DEBUG_PERMISSIONS) {
Slog.i(TAG, "Un-granting permission " + perm
- + " from package " + pkg.getPackageName()
+ + " from package " + friendlyName
+ " (protectionLevel=" + bp.getProtectionLevel()
+ " flags=0x"
+ Integer.toHexString(PackageInfoUtils.appInfoFlags(pkg, ps))
@@ -3035,7 +3032,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
&& (packageOfInterest == null
|| packageOfInterest.equals(pkg.getPackageName()))) {
Slog.i(TAG, "Not granting permission " + perm
- + " to package " + pkg.getPackageName()
+ + " to package " + friendlyName
+ " (protectionLevel=" + bp.getProtectionLevel()
+ " flags=0x"
+ Integer.toHexString(PackageInfoUtils.appInfoFlags(pkg, ps))
@@ -3078,17 +3075,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
* @return user ids for created users and pre-created users
*/
private int[] getAllUserIds() {
- final TimingsTraceLog t = new TimingsTraceLog(TAG, Trace.TRACE_TAG_SYSTEM_SERVER);
- t.traceBegin("getAllUserIds");
- List<UserInfo> users = UserManagerService.getInstance().getUsers(
- /*excludePartial=*/ true, /*excludeDying=*/ true, /*excludePreCreated=*/ false);
- int size = users.size();
- final int[] userIds = new int[size];
- for (int i = 0; i < size; i++) {
- userIds[i] = users.get(i).id;
- }
- t.traceEnd();
- return userIds;
+ return UserManagerService.getInstance().getUserIdsIncludingPreCreated();
}
/**
diff --git a/services/core/java/com/android/server/telecom/InternalServiceRepository.java b/services/core/java/com/android/server/telecom/InternalServiceRepository.java
new file mode 100644
index 000000000000..76ea5c788bd7
--- /dev/null
+++ b/services/core/java/com/android/server/telecom/InternalServiceRepository.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.telecom;
+
+import android.content.Context;
+import android.os.Binder;
+import android.os.Process;
+
+import com.android.internal.telecom.IDeviceIdleControllerAdapter;
+import com.android.internal.telecom.IInternalServiceRetriever;
+import com.android.server.DeviceIdleInternal;
+
+/**
+ * The Telecom APK can not access services stored in LocalService directly and since it is in the
+ * SYSTEM process, it also can not use the *Manager interfaces
+ * (see {@link Context#enforceCallingPermission(String, String)}). Instead, we must wrap these local
+ * services in binder interfaces to allow Telecom access.
+ */
+public class InternalServiceRepository extends IInternalServiceRetriever.Stub {
+
+ private final IDeviceIdleControllerAdapter.Stub mDeviceIdleControllerAdapter =
+ new IDeviceIdleControllerAdapter.Stub() {
+ @Override
+ public void exemptAppTemporarilyForEvent(String packageName, long duration, int userHandle,
+ String reason) {
+ mDeviceIdleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName,
+ duration, userHandle, true /*sync*/, reason);
+ }
+ };
+
+ private final DeviceIdleInternal mDeviceIdleController;
+
+ public InternalServiceRepository(DeviceIdleInternal deviceIdleController) {
+ mDeviceIdleController = deviceIdleController;
+ }
+
+ @Override
+ public IDeviceIdleControllerAdapter getDeviceIdleController() {
+ ensureSystemProcess();
+ return mDeviceIdleControllerAdapter;
+ }
+
+ private void ensureSystemProcess() {
+ if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+ // Correctness check - this should never happen.
+ throw new SecurityException("SYSTEM ONLY API.");
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index a853529f49e4..52ad893a9ace 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -35,7 +35,10 @@ import android.util.IntArray;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.telecom.ITelecomLoader;
+import com.android.internal.telecom.ITelecomService;
import com.android.internal.telephony.SmsApplication;
+import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.pm.UserManagerService;
@@ -53,16 +56,13 @@ public class TelecomLoaderService extends SystemService {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
// Normally, we would listen for death here, but since telecom runs in the same process
- // as this loader (process="system") thats redundant here.
+ // as this loader (process="system") that's redundant here.
try {
- service.linkToDeath(new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- connectToTelecom();
- }
- }, 0);
+ ITelecomLoader telecomLoader = ITelecomLoader.Stub.asInterface(service);
+ ITelecomService telecomService = telecomLoader.createTelecomService(mServiceRepo);
+
SmsApplication.getDefaultMmsApplication(mContext, false);
- ServiceManager.addService(Context.TELECOM_SERVICE, service);
+ ServiceManager.addService(Context.TELECOM_SERVICE, telecomService.asBinder());
synchronized (mLock) {
final PermissionManagerServiceInternal permissionManager =
@@ -114,6 +114,8 @@ public class TelecomLoaderService extends SystemService {
@GuardedBy("mLock")
private TelecomServiceConnection mServiceConnection;
+ private InternalServiceRepository mServiceRepo;
+
public TelecomLoaderService(Context context) {
super(context);
mContext = context;
@@ -129,6 +131,8 @@ public class TelecomLoaderService extends SystemService {
if (phase == PHASE_ACTIVITY_MANAGER_READY) {
registerDefaultAppNotifier();
registerCarrierConfigChangedReceiver();
+ // core services will have already been loaded.
+ setupServiceRepository();
connectToTelecom();
}
}
@@ -154,6 +158,11 @@ public class TelecomLoaderService extends SystemService {
}
}
+ private void setupServiceRepository() {
+ DeviceIdleInternal deviceIdleInternal = getLocalService(DeviceIdleInternal.class);
+ mServiceRepo = new InternalServiceRepository(deviceIdleInternal);
+ }
+
private void registerDefaultAppProviders() {
final PermissionManagerServiceInternal permissionManager =
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 2394bafc09de..26103d5d6c8c 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -123,6 +123,8 @@ public class TrustManagerService extends SystemService {
private static final String TRUST_TIMEOUT_ALARM_TAG = "TrustManagerService.trustTimeoutForUser";
private static final long TRUST_TIMEOUT_IN_MILLIS = 4 * 60 * 60 * 1000;
+ private static final String PRIV_NAMESPACE = "http://schemas.android.com/apk/prv/res/android";
+
private final ArraySet<AgentInfo> mActiveAgents = new ArraySet<>();
private final ArrayList<ITrustListener> mTrustListeners = new ArrayList<>();
private final Receiver mReceiver = new Receiver();
@@ -808,8 +810,8 @@ public class TrustManagerService extends SystemService {
TypedArray sa = res
.obtainAttributes(attrs, com.android.internal.R.styleable.TrustAgent);
cn = sa.getString(com.android.internal.R.styleable.TrustAgent_settingsActivity);
- canUnlockProfile = sa.getBoolean(
- com.android.internal.R.styleable.TrustAgent_unlockProfile, false);
+ canUnlockProfile = attrs.getAttributeBooleanValue(
+ PRIV_NAMESPACE, "unlockProfile", false);
sa.recycle();
} catch (PackageManager.NameNotFoundException e) {
caughtException = e;
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerInternal.java b/services/core/java/com/android/server/uri/UriGrantsManagerInternal.java
index cdb61995c336..5772dea287fc 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerInternal.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerInternal.java
@@ -75,10 +75,31 @@ public interface UriGrantsManagerInternal {
void removeUriPermissionsForPackage(
String packageName, int userHandle, boolean persistable, boolean targetOnly);
/**
- * @param uri This uri must NOT contain an embedded userId.
+ * Remove any {@link UriPermission} associated with the owner whose values match the given
+ * filtering parameters.
+ *
+ * @param token An opaque owner token as returned by {@link #newUriPermissionOwner(String)}.
+ * @param uri This uri must NOT contain an embedded userId. {@code null} to apply to all Uris.
+ * @param mode The modes (as a bitmask) to revoke.
* @param userId The userId in which the uri is to be resolved.
*/
void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId);
+
+ /**
+ * Remove any {@link UriPermission} associated with the owner whose values match the given
+ * filtering parameters.
+ *
+ * @param token An opaque owner token as returned by {@link #newUriPermissionOwner(String)}.
+ * @param uri This uri must NOT contain an embedded userId. {@code null} to apply to all Uris.
+ * @param mode The modes (as a bitmask) to revoke.
+ * @param userId The userId in which the uri is to be resolved.
+ * @param targetPkg Calling package name to match, or {@code null} to apply to all packages.
+ * @param targetUserId Calling user to match, or {@link UserHandle#USER_ALL} to apply to all
+ * users.
+ */
+ void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId,
+ String targetPkg, int targetUserId);
+
boolean checkAuthorityGrants(
int callingUid, ProviderInfo cpi, int userId, boolean checkUser);
void dump(PrintWriter pw, boolean dumpAll, String dumpPackage);
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index f14c3a53940d..8eefd8fa4a91 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -51,7 +51,6 @@ import android.app.AppGlobals;
import android.app.GrantedUriPermission;
import android.app.IUriGrantsManager;
import android.content.ClipData;
-import android.content.ComponentName;
import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.Context;
@@ -88,11 +87,11 @@ import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.SystemServiceManager;
-import libcore.io.IoUtils;
-
import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
+import libcore.io.IoUtils;
+
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
@@ -1431,16 +1430,18 @@ public class UriGrantsManagerService extends IUriGrantsManager.Stub {
@Override
public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId) {
+ revokeUriPermissionFromOwner(token, uri, mode, userId, null, UserHandle.USER_ALL);
+ }
+
+ @Override
+ public void revokeUriPermissionFromOwner(IBinder token, Uri uri, int mode, int userId,
+ String targetPkg, int targetUserId) {
final UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
if (owner == null) {
throw new IllegalArgumentException("Unknown owner: " + token);
}
-
- if (uri == null) {
- owner.removeUriPermissions(mode);
- } else {
- owner.removeUriPermission(new GrantUri(userId, uri, mode), mode);
- }
+ GrantUri grantUri = uri == null ? null : new GrantUri(userId, uri, mode);
+ owner.removeUriPermission(grantUri, mode, targetPkg, targetUserId);
}
@Override
diff --git a/services/core/java/com/android/server/uri/UriPermissionOwner.java b/services/core/java/com/android/server/uri/UriPermissionOwner.java
index 2b404a43a338..0c263997a8b5 100644
--- a/services/core/java/com/android/server/uri/UriPermissionOwner.java
+++ b/services/core/java/com/android/server/uri/UriPermissionOwner.java
@@ -21,6 +21,7 @@ import static android.content.Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
import android.os.Binder;
import android.os.IBinder;
+import android.os.UserHandle;
import android.util.ArraySet;
import android.util.proto.ProtoOutputStream;
@@ -74,30 +75,47 @@ public class UriPermissionOwner {
}
void removeUriPermission(GrantUri grantUri, int mode) {
+ removeUriPermission(grantUri, mode, null, UserHandle.USER_ALL);
+ }
+
+ void removeUriPermission(GrantUri grantUri, int mode, String targetPgk, int targetUserId) {
if ((mode & FLAG_GRANT_READ_URI_PERMISSION) != 0 && mReadPerms != null) {
Iterator<UriPermission> it = mReadPerms.iterator();
while (it.hasNext()) {
UriPermission perm = it.next();
- if (grantUri == null || grantUri.equals(perm.uri)) {
- perm.removeReadOwner(this);
- mService.removeUriPermissionIfNeeded(perm);
- it.remove();
+ if (grantUri != null && !grantUri.equals(perm.uri)) {
+ continue;
+ }
+ if (targetPgk != null && !targetPgk.equals(perm.targetPkg)) {
+ continue;
}
+ if (targetUserId != UserHandle.USER_ALL && targetUserId != perm.targetUserId) {
+ continue;
+ }
+ perm.removeReadOwner(this);
+ mService.removeUriPermissionIfNeeded(perm);
+ it.remove();
}
if (mReadPerms.isEmpty()) {
mReadPerms = null;
}
}
- if ((mode & FLAG_GRANT_WRITE_URI_PERMISSION) != 0
- && mWritePerms != null) {
+ if ((mode & FLAG_GRANT_WRITE_URI_PERMISSION) != 0 && mWritePerms != null) {
Iterator<UriPermission> it = mWritePerms.iterator();
while (it.hasNext()) {
UriPermission perm = it.next();
- if (grantUri == null || grantUri.equals(perm.uri)) {
- perm.removeWriteOwner(this);
- mService.removeUriPermissionIfNeeded(perm);
- it.remove();
+ if (grantUri != null && !grantUri.equals(perm.uri)) {
+ continue;
+ }
+ if (targetPgk != null && !targetPgk.equals(perm.targetPkg)) {
+ continue;
+ }
+ if (targetUserId != UserHandle.USER_ALL && targetUserId != perm.targetUserId) {
+ continue;
}
+ perm.removeWriteOwner(this);
+ mService.removeUriPermissionIfNeeded(perm);
+ it.remove();
}
if (mWritePerms.isEmpty()) {
mWritePerms = null;
diff --git a/services/core/java/com/android/server/vr/Vr2dDisplay.java b/services/core/java/com/android/server/vr/Vr2dDisplay.java
index 3f2b5c231dca..a713e5b13667 100644
--- a/services/core/java/com/android/server/vr/Vr2dDisplay.java
+++ b/services/core/java/com/android/server/vr/Vr2dDisplay.java
@@ -295,6 +295,7 @@ class Vr2dDisplay {
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL;
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_SECURE;
+ flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
DISPLAY_NAME, mVirtualDisplayWidth, mVirtualDisplayHeight, mVirtualDisplayDpi);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 5339d86a7b78..1a13d0fc64c4 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -70,7 +70,7 @@ import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TOP;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.PERSIST_ACROSS_REBOOTS;
import static android.content.pm.ActivityInfo.PERSIST_ROOT_ONLY;
@@ -1680,7 +1680,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (options != null) {
final boolean useLockTask = options.getLockTaskMode();
if (useLockTask && lockTaskLaunchMode == LOCK_TASK_LAUNCH_MODE_DEFAULT) {
- lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
+ lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
}
}
return lockTaskLaunchMode;
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index cd508d0e1860..959aedcd1e4a 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -1990,7 +1990,7 @@ class ActivityStack extends Task {
return mRootWindowContainer.resumeHomeActivity(prev, reason, getDisplayArea());
}
- void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
+ void startActivityLocked(ActivityRecord r, @Nullable ActivityRecord focusedTopActivity,
boolean newTask, boolean keepCurTransition, ActivityOptions options) {
Task rTask = r.getTask();
final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
@@ -3336,7 +3336,11 @@ class ActivityStack extends Task {
// Do not sleep activities in this stack if we're marked as focused and the keyguard
// is in the process of going away.
if (isFocusedStackOnDisplay()
- && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()) {
+ && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()
+ // Avoid resuming activities on secondary displays since we don't want bubble
+ // activities to be resumed while bubble is still collapsed.
+ // TODO(b/113840485): Having keyguard going away state for secondary displays.
+ && display.isDefaultDisplay) {
return false;
}
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index 6bfcf0c75b83..3dd82a6221c6 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -75,9 +75,9 @@ import static com.android.server.wm.RootWindowContainer.TAG_STATES;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_PINNED_TASK;
+import static com.android.server.wm.Task.LOCK_TASK_AUTH_ALLOWLISTED;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
-import static com.android.server.wm.Task.LOCK_TASK_AUTH_WHITELISTED;
import static com.android.server.wm.Task.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -788,7 +788,7 @@ public class ActivityStackSupervisor implements RecentTasks.Callbacks {
final LockTaskController lockTaskController = mService.getLockTaskController();
if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
|| task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV
- || (task.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED
+ || (task.mLockTaskAuth == LOCK_TASK_AUTH_ALLOWLISTED
&& lockTaskController.getLockTaskModeState()
== LOCK_TASK_MODE_LOCKED)) {
lockTaskController.startLockTaskMode(task, false, 0 /* blank UID */);
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index b869eb56f536..a78232c05397 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1697,8 +1697,9 @@ class ActivityStarter {
mRootWindowContainer.sendPowerHintForLaunchStartIfNeeded(
false /* forceSend */, mStartActivity);
- mTargetStack.startActivityLocked(mStartActivity, topStack.getTopNonFinishingActivity(),
- newTask, mKeepCurTransition, mOptions);
+ mTargetStack.startActivityLocked(mStartActivity,
+ topStack != null ? topStack.getTopNonFinishingActivity() : null, newTask,
+ mKeepCurTransition, mOptions);
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index a903bcd3d728..d4dd35f53cf0 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -520,8 +520,8 @@ public abstract class ActivityTaskManagerInternal {
public abstract void onActiveUidsCleared();
public abstract void onUidProcStateChanged(int uid, int procState);
- public abstract void onUidAddedToPendingTempWhitelist(int uid, String tag);
- public abstract void onUidRemovedFromPendingTempWhitelist(int uid);
+ public abstract void onUidAddedToPendingTempAllowlist(int uid, String tag);
+ public abstract void onUidRemovedFromPendingTempAllowlist(int uid);
/** Handle app crash event in {@link android.app.IActivityController} if there is one. */
public abstract boolean handleAppCrashInActivityController(String processName, int pid,
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 52d4b6fc78df..0542ef9b09a4 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -382,7 +382,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
private AppOpsManager mAppOpsManager;
/** All active uids in the system. */
private final MirrorActiveUids mActiveUids = new MirrorActiveUids();
- private final SparseArray<String> mPendingTempWhitelist = new SparseArray<>();
+ private final SparseArray<String> mPendingTempAllowlist = new SparseArray<>();
/** All processes currently running that might have a window organized by name. */
final ProcessMap<WindowProcessController> mProcessNames = new ProcessMap<>();
/** All processes we currently have running mapped by pid and uid */
@@ -1099,7 +1099,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
@Override
public int startActivityIntentSender(IApplicationThread caller, IIntentSender target,
- IBinder whitelistToken, Intent fillInIntent, String resolvedType, IBinder resultTo,
+ IBinder allowlistToken, Intent fillInIntent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int flagsMask, int flagsValues, Bundle bOptions) {
enforceNotIsolatedCaller("startActivityIntentSender");
// Refuse possible leaked file descriptors
@@ -1122,7 +1122,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mAppSwitchesAllowedTime = 0;
}
}
- return pir.sendInner(0, fillInIntent, resolvedType, whitelistToken, null, null,
+ return pir.sendInner(0, fillInIntent, resolvedType, allowlistToken, null, null,
resultTo, resultWho, requestCode, flagsMask, flagsValues, bOptions);
}
@@ -3025,7 +3025,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
// system or a specific app.
// * System-initiated requests will only start the pinned mode (screen pinning)
// * App-initiated requests
- // - will put the device in fully locked mode (LockTask), if the app is whitelisted
+ // - will put the device in fully locked mode (LockTask), if the app is allowlisted
// - will start the pinned mode, otherwise
final int callingUid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
@@ -3073,7 +3073,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
"updateLockTaskPackages()");
}
synchronized (mGlobalLock) {
- if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Whitelisting " + userId + ":"
+ if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Allowlisting " + userId + ":"
+ Arrays.toString(packages));
getLockTaskController().updateLockTaskPackages(userId, packages);
}
@@ -5962,11 +5962,11 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
/**
- * @return whitelist tag for a uid from mPendingTempWhitelist, null if not currently on
- * the whitelist
+ * @return allowlist tag for a uid from mPendingTempAllowlist, null if not currently on
+ * the allowlist
*/
- String getPendingTempWhitelistTagForUidLocked(int uid) {
- return mPendingTempWhitelist.get(uid);
+ String getPendingTempAllowlistTagForUidLocked(int uid) {
+ return mPendingTempAllowlist.get(uid);
}
void logAppTooSlow(WindowProcessController app, long startTime, String msg) {
@@ -7295,16 +7295,16 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
}
@Override
- public void onUidAddedToPendingTempWhitelist(int uid, String tag) {
+ public void onUidAddedToPendingTempAllowlist(int uid, String tag) {
synchronized (mGlobalLockWithoutBoost) {
- mPendingTempWhitelist.put(uid, tag);
+ mPendingTempAllowlist.put(uid, tag);
}
}
@Override
- public void onUidRemovedFromPendingTempWhitelist(int uid) {
+ public void onUidRemovedFromPendingTempAllowlist(int uid) {
synchronized (mGlobalLockWithoutBoost) {
- mPendingTempWhitelist.remove(uid);
+ mPendingTempAllowlist.remove(uid);
}
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index fcbc7564cabb..abfb9c99de6b 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -43,14 +43,14 @@ import static android.view.Display.INVALID_DISPLAY;
import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
+import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_RIGHT_GESTURES;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
-import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
-import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -1573,7 +1573,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
// the heavy operations. This also benefits that the states of multiple activities
// are handled together.
r.linkFixedRotationTransform(prevRotatedLaunchingApp);
- setFixedRotationLaunchingAppUnchecked(r, rotation);
+ if (r != mFixedRotationTransitionListener.mAnimatingRecents) {
+ // Only update the record for normal activity so the display orientation can be
+ // updated when the transition is done if it becomes the top. And the case of
+ // recents can be handled when the recents animation is finished.
+ setFixedRotationLaunchingAppUnchecked(r, rotation);
+ }
return;
}
@@ -4978,7 +4983,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
// Apply restriction if necessary.
- if (needsGestureExclusionRestrictions(w, mLastDispatchedSystemUiVisibility)) {
+ if (needsGestureExclusionRestrictions(w, false /* ignoreRequest */)) {
// Processes the region along the left edge.
remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
@@ -4995,7 +5000,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
outExclusion.op(middle, Op.UNION);
middle.recycle();
} else {
- boolean loggable = needsGestureExclusionRestrictions(w, 0 /* lastSysUiVis */);
+ boolean loggable = needsGestureExclusionRestrictions(w, true /* ignoreRequest */);
if (loggable) {
addToGlobalAndConsumeLimit(local, outExclusion, leftEdge,
Integer.MAX_VALUE, w, EXCLUSION_LEFT);
@@ -5017,17 +5022,21 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
/**
- * @return Whether gesture exclusion area should be restricted from the window depending on the
- * current SystemUI visibility flags.
+ * Returns whether gesture exclusion area should be restricted from the window depending on the
+ * window/activity types and the requested navigation bar visibility and the behavior.
+ *
+ * @param win The target window.
+ * @param ignoreRequest If this is {@code true}, only the window/activity types are considered.
+ * @return {@code true} if the gesture exclusion restrictions are needed.
*/
- private static boolean needsGestureExclusionRestrictions(WindowState win, int sysUiVisibility) {
+ private static boolean needsGestureExclusionRestrictions(WindowState win,
+ boolean ignoreRequest) {
final int type = win.mAttrs.type;
- final int stickyHideNavFlags =
- SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
final boolean stickyHideNav =
- (sysUiVisibility & stickyHideNavFlags) == stickyHideNavFlags;
- return !stickyHideNav && type != TYPE_INPUT_METHOD && type != TYPE_NOTIFICATION_SHADE
- && win.getActivityType() != ACTIVITY_TYPE_HOME;
+ !win.getRequestedInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
+ && win.mAttrs.insetsFlags.behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
+ return (!stickyHideNav || ignoreRequest) && type != TYPE_INPUT_METHOD
+ && type != TYPE_NOTIFICATION_SHADE && win.getActivityType() != ACTIVITY_TYPE_HOME;
}
/**
@@ -5043,7 +5052,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
&& type != TYPE_APPLICATION_STARTING
&& type != TYPE_NAVIGATION_BAR
&& (attrs.flags & FLAG_NOT_TOUCHABLE) == 0
- && needsGestureExclusionRestrictions(win, 0 /* sysUiVisibility */)
+ && needsGestureExclusionRestrictions(win, true /* ignoreRequest */)
&& win.getDisplayContent().mDisplayPolicy.hasSideGestures();
}
@@ -5642,6 +5651,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
*/
private ActivityRecord mAnimatingRecents;
+ /** Whether {@link #mAnimatingRecents} is going to be the top activity. */
+ private boolean mRecentsWillBeTop;
+
/**
* If the recents activity has a fixed orientation which is different from the current top
* activity, it will be rotated before being shown so we avoid a screen rotation animation
@@ -5667,10 +5679,12 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
* If {@link #mAnimatingRecents} still has fixed rotation, it should be moved to top so we
* don't clear {@link #mFixedRotationLaunchingApp} that will be handled by transition.
*/
- void onFinishRecentsAnimation(boolean moveRecentsToBack) {
+ void onFinishRecentsAnimation() {
final ActivityRecord animatingRecents = mAnimatingRecents;
+ final boolean recentsWillBeTop = mRecentsWillBeTop;
mAnimatingRecents = null;
- if (!moveRecentsToBack) {
+ mRecentsWillBeTop = false;
+ if (recentsWillBeTop) {
// The recents activity will be the top, such as staying at recents list or
// returning to home (if home and recents are the same activity).
return;
@@ -5693,6 +5707,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
}
+ void notifyRecentsWillBeTop() {
+ mRecentsWillBeTop = true;
+ }
+
/**
* Return {@code true} if there is an ongoing animation to the "Recents" activity and this
* activity as a fixed orientation so shouldn't be rotated.
@@ -5713,6 +5731,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
if (r == null || r == mAnimatingRecents) {
return;
}
+ if (mAnimatingRecents != null && mRecentsWillBeTop) {
+ // The activity is not the recents and it should be moved to back later, so it is
+ // better to keep its current appearance for the next transition. Otherwise the
+ // display orientation may be updated too early and the layout procedures at the
+ // end of finishing recents animation is skipped. That causes flickering because
+ // the surface of closing app hasn't updated to invisible.
+ return;
+ }
if (mFixedRotationLaunchingApp == null) {
// In most cases this is a no-op if the activity doesn't have fixed rotation.
// Otherwise it could be from finishing recents animation while the display has
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 5c5ec358d004..4a40fc6e572c 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -29,6 +29,9 @@ import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
+import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
+import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
+import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
@@ -71,6 +74,7 @@ import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_M
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
@@ -246,7 +250,8 @@ public class DisplayPolicy {
| View.STATUS_BAR_TRANSPARENT
| View.NAVIGATION_BAR_TRANSPARENT;
- private static final int[] SHOW_TYPES_FOR_SWIPE = {ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR};
+ private static final int[] SHOW_TYPES_FOR_SWIPE =
+ {ITYPE_NAVIGATION_BAR, ITYPE_STATUS_BAR, ITYPE_CLIMATE_BAR, ITYPE_EXTRA_NAVIGATION_BAR};
private static final int[] SHOW_TYPES_FOR_PANIC = {ITYPE_NAVIGATION_BAR};
private final WindowManagerService mService;
@@ -332,6 +337,16 @@ public class DisplayPolicy {
private WindowState mNavigationBarAlt = null;
@WindowManagerPolicy.AltBarPosition
private int mNavigationBarAltPosition = ALT_BAR_UNKNOWN;
+ // Alternative climate bar for when flexible insets mapping is used to place a climate bar on
+ // the screen.
+ private WindowState mClimateBarAlt = null;
+ @WindowManagerPolicy.AltBarPosition
+ private int mClimateBarAltPosition = ALT_BAR_UNKNOWN;
+ // Alternative extra nav bar for when flexible insets mapping is used to place an extra nav bar
+ // on the screen.
+ private WindowState mExtraNavBarAlt = null;
+ @WindowManagerPolicy.AltBarPosition
+ private int mExtraNavBarAltPosition = ALT_BAR_UNKNOWN;
/** See {@link #getNavigationBarFrameHeight} */
private int[] mNavigationBarFrameHeightForRotationDefault = new int[4];
@@ -668,6 +683,12 @@ public class DisplayPolicy {
if (mNavigationBarAlt != null && mNavigationBarAltPosition == pos) {
requestTransientBars(mNavigationBarAlt);
}
+ if (mClimateBarAlt != null && mClimateBarAltPosition == pos) {
+ requestTransientBars(mClimateBarAlt);
+ }
+ if (mExtraNavBarAlt != null && mExtraNavBarAltPosition == pos) {
+ requestTransientBars(mExtraNavBarAlt);
+ }
}
void systemReady() {
@@ -939,6 +960,12 @@ public class DisplayPolicy {
if (mNavigationBarAlt == win) {
mNavigationBarAltPosition = getAltBarPosition(attrs);
}
+ if (mClimateBarAlt == win) {
+ mClimateBarAltPosition = getAltBarPosition(attrs);
+ }
+ if (mExtraNavBarAlt == win) {
+ mExtraNavBarAltPosition = getAltBarPosition(attrs);
+ }
}
/**
@@ -1046,6 +1073,16 @@ public class DisplayPolicy {
return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
}
break;
+ case ITYPE_CLIMATE_BAR:
+ if (mClimateBarAlt != null && mClimateBarAlt.isAlive()) {
+ return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
+ }
+ break;
+ case ITYPE_EXTRA_NAVIGATION_BAR:
+ if (mExtraNavBarAlt != null && mExtraNavBarAlt.isAlive()) {
+ return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
+ }
+ break;
}
}
}
@@ -1151,6 +1188,14 @@ public class DisplayPolicy {
mNavigationBarController.setWindow(mNavigationBarAlt);
mNavigationBarAltPosition = getAltBarPosition(attrs);
break;
+ case ITYPE_CLIMATE_BAR:
+ mClimateBarAlt = win;
+ mClimateBarAltPosition = getAltBarPosition(attrs);
+ break;
+ case ITYPE_EXTRA_NAVIGATION_BAR:
+ mExtraNavBarAlt = win;
+ mExtraNavBarAltPosition = getAltBarPosition(attrs);
+ break;
}
mDisplayContent.setInsetProvider(insetsType, win, null);
}
@@ -1199,6 +1244,8 @@ public class DisplayPolicy {
switch (insetsType) {
case ITYPE_NAVIGATION_BAR:
case ITYPE_STATUS_BAR:
+ case ITYPE_CLIMATE_BAR:
+ case ITYPE_EXTRA_NAVIGATION_BAR:
case ITYPE_CAPTION_BAR:
if (++count > 1) {
throw new IllegalArgumentException(
@@ -1230,6 +1277,12 @@ public class DisplayPolicy {
if (mDisplayContent.isDefaultDisplay) {
mService.mPolicy.setKeyguardCandidateLw(null);
}
+ } else if (mClimateBarAlt == win) {
+ mClimateBarAlt = null;
+ mDisplayContent.setInsetProvider(ITYPE_CLIMATE_BAR, null, null);
+ } else if (mExtraNavBarAlt == win) {
+ mExtraNavBarAlt = null;
+ mDisplayContent.setInsetProvider(ITYPE_EXTRA_NAVIGATION_BAR, null, null);
}
if (mLastFocusedWindow == win) {
mLastFocusedWindow = null;
@@ -1318,7 +1371,8 @@ public class DisplayPolicy {
return R.anim.dock_left_enter;
}
}
- } else if (win == mStatusBarAlt || win == mNavigationBarAlt) {
+ } else if (win == mStatusBarAlt || win == mNavigationBarAlt || win == mClimateBarAlt
+ || win == mExtraNavBarAlt) {
if (win.getAttrs().windowAnimations != 0) {
return ANIMATION_STYLEABLE;
}
@@ -1538,7 +1592,7 @@ public class DisplayPolicy {
if (mInputConsumer == null) {
return;
}
- showNavigationBar();
+ showSystemBars();
// Any user activity always causes us to show the
// navigation controls, if they had been hidden.
// We also clear the low profile and only content
@@ -1573,13 +1627,13 @@ public class DisplayPolicy {
}
}
- private void showNavigationBar() {
+ private void showSystemBars() {
final InsetsSourceProvider provider = mDisplayContent.getInsetsStateController()
.peekSourceProvider(ITYPE_NAVIGATION_BAR);
final InsetsControlTarget target =
provider != null ? provider.getControlTarget() : null;
if (target != null) {
- target.showInsets(Type.navigationBars(), false /* fromIme */);
+ target.showInsets(Type.systemBars(), false /* fromIme */);
}
}
}
@@ -2191,6 +2245,13 @@ public class DisplayPolicy {
df.set(left, top, dfu.right - right, dfu.bottom - bottom);
if (attached == null) {
pf.set(df);
+ if ((pfl & PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME) != 0) {
+ final InsetsSource source = mDisplayContent.getInsetsPolicy()
+ .getInsetsForDispatch(win).peekSource(ITYPE_IME);
+ if (source != null) {
+ pf.inset(source.calculateInsets(pf, false /* ignoreVisibility */));
+ }
+ }
vf.set(adjust != SOFT_INPUT_ADJUST_NOTHING
? displayFrames.mCurrent : displayFrames.mDock);
} else {
@@ -3338,6 +3399,10 @@ public class DisplayPolicy {
(requestedState.getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR)
? Type.navigationBars() : 0)
| (requestedState.getSourceOrDefaultVisibility(ITYPE_STATUS_BAR)
+ ? Type.statusBars() : 0)
+ | (requestedState.getSourceOrDefaultVisibility(ITYPE_EXTRA_NAVIGATION_BAR)
+ ? Type.navigationBars() : 0)
+ | (requestedState.getSourceOrDefaultVisibility(ITYPE_CLIMATE_BAR)
? Type.statusBars() : 0);
if (swipeTarget == mNavigationBar
@@ -4037,6 +4102,16 @@ public class DisplayPolicy {
pw.print(prefix); pw.print("mNavigationBarAltPosition=");
pw.println(mNavigationBarAltPosition);
}
+ if (mClimateBarAlt != null) {
+ pw.print(prefix); pw.print("mClimateBarAlt="); pw.println(mClimateBarAlt);
+ pw.print(prefix); pw.print("mClimateBarAltPosition=");
+ pw.println(mClimateBarAltPosition);
+ }
+ if (mExtraNavBarAlt != null) {
+ pw.print(prefix); pw.print("mExtraNavBarAlt="); pw.println(mExtraNavBarAlt);
+ pw.print(prefix); pw.print("mExtraNavBarAltPosition=");
+ pw.println(mExtraNavBarAltPosition);
+ }
if (mFocusedWindow != null) {
pw.print(prefix); pw.print("mFocusedWindow="); pw.println(mFocusedWindow);
}
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 8e6a2656fce3..9fdfbd0a09da 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -16,6 +16,8 @@
package com.android.server.wm;
+import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
+import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
@@ -94,7 +96,8 @@ class InsetsSourceProvider {
new Point());
final int type = source.getType();
- if (type == ITYPE_STATUS_BAR || type == ITYPE_NAVIGATION_BAR) {
+ if (type == ITYPE_STATUS_BAR || type == ITYPE_NAVIGATION_BAR || type == ITYPE_CLIMATE_BAR
+ || type == ITYPE_EXTRA_NAVIGATION_BAR) {
mControllable = sNewInsetsMode == NEW_INSETS_MODE_FULL;
} else if (type == ITYPE_IME) {
mControllable = sNewInsetsMode >= NEW_INSETS_MODE_IME;
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 77bd4a47a884..68405c40ce37 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -19,6 +19,8 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
+import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
+import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_INVALID;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
@@ -43,6 +45,7 @@ import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.InsetsState.InternalInsetsType;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams.WindowType;
import com.android.server.inputmethod.InputMethodManagerInternal;
import com.android.server.protolog.common.ProtoLog;
@@ -112,7 +115,7 @@ class InsetsStateController {
}
InsetsState getInsetsForWindowMetrics(@NonNull WindowManager.LayoutParams attrs) {
- final @InternalInsetsType int type = getInsetsTypeForWindowType(attrs.type);
+ final @InternalInsetsType int type = getInsetsTypeForLayoutParams(attrs);
final WindowToken token = mDisplayContent.getWindowToken(attrs.token);
final @WindowingMode int windowingMode = token != null
? token.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
@@ -132,7 +135,9 @@ class InsetsStateController {
return false;
}
- private static @InternalInsetsType int getInsetsTypeForWindowType(int type) {
+ private static @InternalInsetsType
+ int getInsetsTypeForLayoutParams(WindowManager.LayoutParams attrs) {
+ @WindowType int type = attrs.type;
switch (type) {
case TYPE_STATUS_BAR:
return ITYPE_STATUS_BAR;
@@ -140,9 +145,22 @@ class InsetsStateController {
return ITYPE_NAVIGATION_BAR;
case TYPE_INPUT_METHOD:
return ITYPE_IME;
- default:
- return ITYPE_INVALID;
}
+
+ // If not one of the types above, check whether an internal inset mapping is specified.
+ if (attrs.providesInsetsTypes != null) {
+ for (@InternalInsetsType int insetsType : attrs.providesInsetsTypes) {
+ switch (insetsType) {
+ case ITYPE_STATUS_BAR:
+ case ITYPE_NAVIGATION_BAR:
+ case ITYPE_CLIMATE_BAR:
+ case ITYPE_EXTRA_NAVIGATION_BAR:
+ return insetsType;
+ }
+ }
+ }
+
+ return ITYPE_INVALID;
}
/** @see #getInsetsForDispatch */
@@ -155,14 +173,15 @@ class InsetsStateController {
state.removeSource(type);
// Navigation bar doesn't get influenced by anything else
- if (type == ITYPE_NAVIGATION_BAR) {
+ if (type == ITYPE_NAVIGATION_BAR || type == ITYPE_EXTRA_NAVIGATION_BAR) {
state.removeSource(ITYPE_IME);
state.removeSource(ITYPE_STATUS_BAR);
+ state.removeSource(ITYPE_CLIMATE_BAR);
state.removeSource(ITYPE_CAPTION_BAR);
}
// Status bar doesn't get influenced by caption bar
- if (type == ITYPE_STATUS_BAR) {
+ if (type == ITYPE_STATUS_BAR || type == ITYPE_CLIMATE_BAR) {
state.removeSource(ITYPE_CAPTION_BAR);
}
@@ -280,6 +299,7 @@ class InsetsStateController {
}
if (changed) {
notifyInsetsChanged();
+ mDisplayContent.updateSystemGestureExclusion();
mDisplayContent.getDisplayPolicy().updateSystemUiVisibilityLw();
}
}
@@ -331,8 +351,12 @@ class InsetsStateController {
@Nullable InsetsControlTarget fakeNavControlling) {
onControlChanged(ITYPE_STATUS_BAR, statusControlling);
onControlChanged(ITYPE_NAVIGATION_BAR, navControlling);
+ onControlChanged(ITYPE_CLIMATE_BAR, statusControlling);
+ onControlChanged(ITYPE_EXTRA_NAVIGATION_BAR, navControlling);
onControlFakeTargetChanged(ITYPE_STATUS_BAR, fakeStatusControlling);
onControlFakeTargetChanged(ITYPE_NAVIGATION_BAR, fakeNavControlling);
+ onControlFakeTargetChanged(ITYPE_CLIMATE_BAR, fakeStatusControlling);
+ onControlFakeTargetChanged(ITYPE_EXTRA_NAVIGATION_BAR, fakeNavControlling);
notifyPendingInsetsControlChanged();
}
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 892ee717e21f..c36dede013f4 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -33,11 +33,11 @@ import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTAS
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_LOCKTASK;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.Task.LOCK_TASK_AUTH_ALLOWLISTED;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_DONT_LOCK;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
import static com.android.server.wm.Task.LOCK_TASK_AUTH_PINNABLE;
-import static com.android.server.wm.Task.LOCK_TASK_AUTH_WHITELISTED;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -264,12 +264,12 @@ public class LockTaskController {
}
/**
- * @return whether the requested task is allowed to be locked (either whitelisted, or declares
+ * @return whether the requested task is allowed to be locked (either allowlisted, or declares
* lockTaskMode="always" in the manifest).
*/
- boolean isTaskWhitelisted(Task task) {
+ boolean isTaskAllowlisted(Task task) {
switch(task.mLockTaskAuth) {
- case LOCK_TASK_AUTH_WHITELISTED:
+ case LOCK_TASK_AUTH_ALLOWLISTED:
case LOCK_TASK_AUTH_LAUNCHABLE:
case LOCK_TASK_AUTH_LAUNCHABLE_PRIV:
return true;
@@ -311,7 +311,7 @@ public class LockTaskController {
private boolean isLockTaskModeViolationInternal(Task task, boolean isNewClearTask) {
// TODO: Double check what's going on here. If the task is already in lock task mode, it's
- // likely whitelisted, so will return false below.
+ // likely allowlisted, so will return false below.
if (isTaskLocked(task) && !isNewClearTask) {
// If the task is already at the top and won't be cleared, then allow the operation
return false;
@@ -327,7 +327,7 @@ public class LockTaskController {
return false;
}
- return !(isTaskWhitelisted(task) || mLockTaskModeTasks.isEmpty());
+ return !(isTaskAllowlisted(task) || mLockTaskModeTasks.isEmpty());
}
private boolean isRecentsAllowed(int userId) {
@@ -356,7 +356,7 @@ public class LockTaskController {
return false;
default:
}
- return isPackageWhitelisted(userId, packageName);
+ return isPackageAllowlisted(userId, packageName);
}
private boolean isEmergencyCallTask(Task task) {
@@ -556,7 +556,7 @@ public class LockTaskController {
if (!isSystemCaller) {
task.mLockTaskUid = callingUid;
if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) {
- // startLockTask() called by app, but app is not part of lock task whitelist. Show
+ // startLockTask() called by app, but app is not part of lock task allowlist. Show
// app pinning request. We will come back here with isSystemCaller true.
if (DEBUG_LOCKTASK) Slog.w(TAG_LOCKTASK, "Mode default, asking user");
StatusBarManagerInternal statusBarManager = LocalServices.getService(
@@ -649,8 +649,8 @@ public class LockTaskController {
/**
* Update packages that are allowed to be launched in lock task mode.
- * @param userId Which user this whitelist is associated with
- * @param packages The whitelist of packages allowed in lock task mode
+ * @param userId Which user this allowlist is associated with
+ * @param packages The allowlist of packages allowed in lock task mode
* @see #mLockTaskPackages
*/
void updateLockTaskPackages(int userId, String[] packages) {
@@ -659,19 +659,19 @@ public class LockTaskController {
boolean taskChanged = false;
for (int taskNdx = mLockTaskModeTasks.size() - 1; taskNdx >= 0; --taskNdx) {
final Task lockedTask = mLockTaskModeTasks.get(taskNdx);
- final boolean wasWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
- || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
+ final boolean wasAllowlisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
+ || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_ALLOWLISTED;
lockedTask.setLockTaskAuth();
- final boolean isWhitelisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
- || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED;
+ final boolean isAllowlisted = lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
+ || lockedTask.mLockTaskAuth == LOCK_TASK_AUTH_ALLOWLISTED;
if (mLockTaskModeState != LOCK_TASK_MODE_LOCKED
|| lockedTask.mUserId != userId
- || !wasWhitelisted || isWhitelisted) {
+ || !wasAllowlisted || isAllowlisted) {
continue;
}
- // Terminate locked tasks that have recently lost whitelist authorization.
+ // Terminate locked tasks that have recently lost allowlist authorization.
if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "onLockTaskPackagesUpdated: removing " +
lockedTask + " mLockTaskAuth()=" + lockedTask.lockTaskAuthToString());
removeLockedTask(lockedTask);
@@ -697,17 +697,17 @@ public class LockTaskController {
}
}
- boolean isPackageWhitelisted(int userId, String pkg) {
+ boolean isPackageAllowlisted(int userId, String pkg) {
if (pkg == null) {
return false;
}
- String[] whitelist;
- whitelist = mLockTaskPackages.get(userId);
- if (whitelist == null) {
+ String[] allowlist;
+ allowlist = mLockTaskPackages.get(userId);
+ if (allowlist == null) {
return false;
}
- for (String whitelistedPkg : whitelist) {
- if (pkg.equals(whitelistedPkg)) {
+ for (String allowlistedPkg : allowlist) {
+ if (pkg.equals(allowlistedPkg)) {
return true;
}
}
diff --git a/services/core/java/com/android/server/wm/PolicyControl.java b/services/core/java/com/android/server/wm/PolicyControl.java
index 0f92bc83a666..61b6e0b25961 100644
--- a/services/core/java/com/android/server/wm/PolicyControl.java
+++ b/services/core/java/com/android/server/wm/PolicyControl.java
@@ -196,40 +196,40 @@ class PolicyControl {
private static final String ALL = "*";
private static final String APPS = "apps";
- private final ArraySet<String> mWhitelist;
- private final ArraySet<String> mBlacklist;
+ private final ArraySet<String> mAllowlist;
+ private final ArraySet<String> mDenylist;
- private Filter(ArraySet<String> whitelist, ArraySet<String> blacklist) {
- mWhitelist = whitelist;
- mBlacklist = blacklist;
+ private Filter(ArraySet<String> allowlist, ArraySet<String> denylist) {
+ mAllowlist = allowlist;
+ mDenylist = denylist;
}
boolean matches(LayoutParams attrs) {
if (attrs == null) return false;
boolean isApp = attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
&& attrs.type <= WindowManager.LayoutParams.LAST_APPLICATION_WINDOW;
- if (isApp && mBlacklist.contains(APPS)) return false;
- if (onBlacklist(attrs.packageName)) return false;
- if (isApp && mWhitelist.contains(APPS)) return true;
- return onWhitelist(attrs.packageName);
+ if (isApp && mDenylist.contains(APPS)) return false;
+ if (onDenylist(attrs.packageName)) return false;
+ if (isApp && mAllowlist.contains(APPS)) return true;
+ return onAllowlist(attrs.packageName);
}
boolean matches(String packageName) {
- return !onBlacklist(packageName) && onWhitelist(packageName);
+ return !onDenylist(packageName) && onAllowlist(packageName);
}
- private boolean onBlacklist(String packageName) {
- return mBlacklist.contains(packageName) || mBlacklist.contains(ALL);
+ private boolean onDenylist(String packageName) {
+ return mDenylist.contains(packageName) || mDenylist.contains(ALL);
}
- private boolean onWhitelist(String packageName) {
- return mWhitelist.contains(ALL) || mWhitelist.contains(packageName);
+ private boolean onAllowlist(String packageName) {
+ return mAllowlist.contains(ALL) || mAllowlist.contains(packageName);
}
void dump(PrintWriter pw) {
pw.print("Filter[");
- dump("whitelist", mWhitelist, pw); pw.print(',');
- dump("blacklist", mBlacklist, pw); pw.print(']');
+ dump("allowlist", mAllowlist, pw); pw.print(',');
+ dump("denylist", mDenylist, pw); pw.print(']');
}
private void dump(String name, ArraySet<String> set, PrintWriter pw) {
@@ -253,18 +253,18 @@ class PolicyControl {
// e.g. "com.package1", or "apps, com.android.keyguard" or "*"
static Filter parse(String value) {
if (value == null) return null;
- ArraySet<String> whitelist = new ArraySet<String>();
- ArraySet<String> blacklist = new ArraySet<String>();
+ ArraySet<String> allowlist = new ArraySet<String>();
+ ArraySet<String> denylist = new ArraySet<String>();
for (String token : value.split(",")) {
token = token.trim();
if (token.startsWith("-") && token.length() > 1) {
token = token.substring(1);
- blacklist.add(token);
+ denylist.add(token);
} else {
- whitelist.add(token);
+ allowlist.add(token);
}
}
- return new Filter(whitelist, blacklist);
+ return new Filter(allowlist, denylist);
}
}
}
diff --git a/services/core/java/com/android/server/wm/RecentTasks.java b/services/core/java/com/android/server/wm/RecentTasks.java
index 851b533a550d..3fe75a4ab49e 100644
--- a/services/core/java/com/android/server/wm/RecentTasks.java
+++ b/services/core/java/com/android/server/wm/RecentTasks.java
@@ -655,7 +655,8 @@ class RecentTasks {
}
for (int i = mTasks.size() - 1; i >= 0; --i) {
final Task task = mTasks.get(i);
- if (task.mUserId == userId && !mService.getLockTaskController().isTaskWhitelisted(task)) {
+ if (task.mUserId == userId
+ && !mService.getLockTaskController().isTaskAllowlisted(task)) {
remove(task);
}
}
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index a2b295a609cd..65db23c714a9 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -702,6 +702,11 @@ public class RecentsAnimationController implements DeathRecipient {
"cleanupAnimation(): Notify animation finished mPendingAnimations=%d "
+ "reorderMode=%d",
mPendingAnimations.size(), reorderMode);
+ if (reorderMode != REORDER_MOVE_TO_ORIGINAL_POSITION) {
+ // Notify the state at the beginning because the removeAnimation may notify the
+ // transition is finished. This is a signal that there will be a next transition.
+ mDisplayContent.mFixedRotationTransitionListener.notifyRecentsWillBeTop();
+ }
for (int i = mPendingAnimations.size() - 1; i >= 0; i--) {
final TaskAnimationAdapter taskAdapter = mPendingAnimations.get(i);
if (reorderMode == REORDER_MOVE_TO_TOP || reorderMode == REORDER_KEEP_IN_PLACE) {
@@ -742,8 +747,7 @@ public class RecentsAnimationController implements DeathRecipient {
mTargetActivityRecord.token);
}
}
- mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(
- reorderMode == REORDER_MOVE_TO_ORIGINAL_POSITION /* moveRecentsToBack */);
+ mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation();
// Notify that the animation has ended
if (mStatusBar != null) {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 049e46fb6cef..a65eca832f48 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2305,10 +2305,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent display = getChildAt(displayNdx);
- if (display.shouldSleep()) {
- continue;
- }
-
boolean resumedOnDisplay = false;
for (int tdaNdx = display.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
final TaskDisplayArea taskDisplayArea = display.getTaskDisplayAreaAt(tdaNdx);
@@ -2590,7 +2586,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
mDisplayAccessUIDs.clear();
for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) {
final DisplayContent displayContent = getChildAt(displayNdx);
- // Only bother calculating the whitelist for private displays
+ // Only bother calculating the allowlist for private displays
if (displayContent.isPrivate()) {
mDisplayAccessUIDs.append(
displayContent.mDisplayId, displayContent.getPresentUIDs());
diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java
index b71ecbb8a72d..ede6708d5f8f 100644
--- a/services/core/java/com/android/server/wm/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java
@@ -233,10 +233,10 @@ public class SafeActivityOptions {
Slog.w(TAG, msg);
throw new SecurityException(msg);
}
- // Check if someone tries to launch an unwhitelisted activity into LockTask mode.
+ // Check if someone tries to launch an unallowlisted activity into LockTask mode.
final boolean lockTaskMode = options.getLockTaskMode();
if (aInfo != null && lockTaskMode
- && !supervisor.mService.getLockTaskController().isPackageWhitelisted(
+ && !supervisor.mService.getLockTaskController().isPackageAllowlisted(
UserHandle.getUserId(callingUid), aInfo.packageName)) {
final String msg = "Permission Denial: starting " + getIntentString(intent)
+ " from " + callerApp + " (pid=" + callingPid
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 76927e277412..3a750f2c9da3 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -40,7 +40,7 @@ import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
@@ -264,7 +264,7 @@ class Task extends WindowContainer<WindowContainer> {
/** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
/** Can enter lockTask without user approval. Can start over existing lockTask task. */
- final static int LOCK_TASK_AUTH_WHITELISTED = 3;
+ final static int LOCK_TASK_AUTH_ALLOWLISTED = 3;
/** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
* lockTask task. */
final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
@@ -1377,7 +1377,7 @@ class Task extends WindowContainer<WindowContainer> {
getDisplayArea().addStackReferenceIfNeeded((ActivityStack) child);
}
- // Make sure the list of display UID whitelists is updated
+ // Make sure the list of display UID allowlists is updated
// now that this record is in a new task.
mRootWindowContainer.updateUIDsPresentOnDisplay();
@@ -1605,7 +1605,7 @@ class Task extends WindowContainer<WindowContainer> {
case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
- case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
+ case LOCK_TASK_AUTH_ALLOWLISTED: return "LOCK_TASK_AUTH_ALLOWLISTED";
case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
default: return "unknown=" + mLockTaskAuth;
}
@@ -1625,8 +1625,8 @@ class Task extends WindowContainer<WindowContainer> {
final LockTaskController lockTaskController = mAtmService.getLockTaskController();
switch (r.lockTaskLaunchMode) {
case LOCK_TASK_LAUNCH_MODE_DEFAULT:
- mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
- ? LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
+ mLockTaskAuth = lockTaskController.isPackageAllowlisted(mUserId, pkg)
+ ? LOCK_TASK_AUTH_ALLOWLISTED : LOCK_TASK_AUTH_PINNABLE;
break;
case LOCK_TASK_LAUNCH_MODE_NEVER:
@@ -1637,8 +1637,8 @@ class Task extends WindowContainer<WindowContainer> {
mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
break;
- case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
- mLockTaskAuth = lockTaskController.isPackageWhitelisted(mUserId, pkg)
+ case LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED:
+ mLockTaskAuth = lockTaskController.isPackageAllowlisted(mUserId, pkg)
? LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
break;
}
@@ -3627,6 +3627,9 @@ class Task extends WindowContainer<WindowContainer> {
info.topActivityInfo = mReuseActivitiesReport.top != null
? mReuseActivitiesReport.top.info
: null;
+ info.requestedOrientation = mReuseActivitiesReport.base != null
+ ? mReuseActivitiesReport.base.getRequestedOrientation()
+ : SCREEN_ORIENTATION_UNSET;
}
/**
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index f70bf18cdea5..e153befde8ad 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -458,7 +458,8 @@ class TaskOrganizerController extends ITaskOrganizerController.Stub {
|| mTmpTaskInfo.topActivityType != lastInfo.topActivityType
|| mTmpTaskInfo.isResizeable != lastInfo.isResizeable
|| mTmpTaskInfo.pictureInPictureParams != lastInfo.pictureInPictureParams
- || !TaskDescription.equals(mTmpTaskInfo.taskDescription, lastInfo.taskDescription);
+ || !TaskDescription.equals(mTmpTaskInfo.taskDescription, lastInfo.taskDescription)
+ || mTmpTaskInfo.requestedOrientation != lastInfo.requestedOrientation;
if (!changed) {
int cfgChanges = mTmpTaskInfo.configuration.diff(lastInfo.configuration);
final int winCfgChanges = (cfgChanges & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 86aacf308068..1716dcd5ee16 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -531,7 +531,7 @@ class WindowToken extends WindowContainer<WindowState> {
void applyFixedRotationTransform(DisplayInfo info, DisplayFrames displayFrames,
Configuration config) {
if (mFixedRotationTransformState != null) {
- return;
+ cleanUpFixedRotationTransformState(true /* replacing */);
}
mFixedRotationTransformState = new FixedRotationTransformState(info, displayFrames,
new Configuration(config), mDisplayContent.getRotation());
@@ -548,13 +548,13 @@ class WindowToken extends WindowContainer<WindowState> {
* one. This takes the same effect as {@link #applyFixedRotationTransform}.
*/
void linkFixedRotationTransform(WindowToken other) {
- if (mFixedRotationTransformState != null) {
- return;
- }
final FixedRotationTransformState fixedRotationState = other.mFixedRotationTransformState;
- if (fixedRotationState == null) {
+ if (fixedRotationState == null || mFixedRotationTransformState == fixedRotationState) {
return;
}
+ if (mFixedRotationTransformState != null) {
+ cleanUpFixedRotationTransformState(true /* replacing */);
+ }
mFixedRotationTransformState = fixedRotationState;
fixedRotationState.mAssociatedTokens.add(this);
onConfigurationChanged(getParent().getConfiguration());
@@ -609,11 +609,17 @@ class WindowToken extends WindowContainer<WindowState> {
// The state is cleared at the end, because it is used to indicate that other windows can
// use seamless rotation when applying rotation to display.
for (int i = state.mAssociatedTokens.size() - 1; i >= 0; i--) {
- state.mAssociatedTokens.get(i).cleanUpFixedRotationTransformState();
+ state.mAssociatedTokens.get(i).cleanUpFixedRotationTransformState(
+ false /* replacing */);
}
}
- private void cleanUpFixedRotationTransformState() {
+ private void cleanUpFixedRotationTransformState(boolean replacing) {
+ if (replacing && mFixedRotationTransformState.mAssociatedTokens.size() > 1) {
+ // The state is not only used by self. Make sure to leave the influence by others.
+ mFixedRotationTransformState.mAssociatedTokens.remove(this);
+ mFixedRotationTransformState.mRotatedContainers.remove(this);
+ }
mFixedRotationTransformState = null;
notifyFixedRotationTransform(false /* enabled */);
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index 925ad0f57f19..460842e56764 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -106,6 +106,7 @@ cc_defaults {
"libkeystore_binder",
"libmtp",
"libnativehelper",
+ "libprocessgroup",
"libutils",
"libui",
"libinput",
diff --git a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
index 6a6da0e2b395..678308af34ea 100644
--- a/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
+++ b/services/core/jni/com_android_server_am_CachedAppOptimizer.cpp
@@ -29,11 +29,16 @@
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
+#include <binder/IPCThreadState.h>
#include <jni.h>
+#include <processgroup/processgroup.h>
using android::base::StringPrintf;
using android::base::WriteStringToFile;
+#define SYNC_RECEIVED_WHILE_FROZEN (1)
+#define ASYNC_RECEIVED_WHILE_FROZEN (2)
+
namespace android {
// This performs per-process reclaim on all processes belonging to non-app UIDs.
@@ -74,9 +79,60 @@ static void com_android_server_am_CachedAppOptimizer_compactSystem(JNIEnv *, job
}
}
+static void com_android_server_am_CachedAppOptimizer_enableFreezerInternal(
+ JNIEnv *env, jobject clazz, jboolean enable) {
+ bool success = true;
+
+ if (enable) {
+ success = SetTaskProfiles(0, {"FreezerEnabled"}, true);
+ } else {
+ success = SetTaskProfiles(0, {"FreezerDisabled"}, true);
+ }
+
+ if (!success) {
+ jniThrowException(env, "java/lang/RuntimeException", "Unknown error");
+ }
+}
+
+static void com_android_server_am_CachedAppOptimizer_freezeBinder(
+ JNIEnv *env, jobject clazz, jint pid, jboolean freeze) {
+
+ if (IPCThreadState::freeze(pid, freeze, 100 /* timeout [ms] */) != 0) {
+ jniThrowException(env, "java/lang/RuntimeException", "Unable to freeze/unfreeze binder");
+ }
+}
+
+static jint com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo(JNIEnv *env,
+ jobject clazz, jint pid) {
+ bool syncReceived = false, asyncReceived = false;
+
+ int error = IPCThreadState::getProcessFreezeInfo(pid, &syncReceived, &asyncReceived);
+
+ if (error < 0) {
+ jniThrowException(env, "java/lang/RuntimeException", strerror(error));
+ }
+
+ jint retVal = 0;
+
+ if(syncReceived) {
+ retVal |= SYNC_RECEIVED_WHILE_FROZEN;;
+ }
+
+ if(asyncReceived) {
+ retVal |= ASYNC_RECEIVED_WHILE_FROZEN;
+ }
+
+ return retVal;
+}
+
static const JNINativeMethod sMethods[] = {
/* name, signature, funcPtr */
{"compactSystem", "()V", (void*)com_android_server_am_CachedAppOptimizer_compactSystem},
+ {"enableFreezerInternal", "(Z)V",
+ (void*)com_android_server_am_CachedAppOptimizer_enableFreezerInternal},
+ {"freezeBinder", "(IZ)V", (void*)com_android_server_am_CachedAppOptimizer_freezeBinder},
+ {"getBinderFreezeInfo", "(I)I",
+ (void*)com_android_server_am_CachedAppOptimizer_getBinderFreezeInfo}
};
int register_android_server_am_CachedAppOptimizer(JNIEnv* env)
diff --git a/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java b/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java
index 27a116c8043e..1586a33ba0e9 100644
--- a/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java
+++ b/services/systemcaptions/java/com/android/server/systemcaptions/SystemCaptionsManagerService.java
@@ -34,7 +34,8 @@ public final class SystemCaptionsManagerService extends
context,
com.android.internal.R.string.config_defaultSystemCaptionsManagerService),
/*disallowProperty=*/ null,
- /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_EAGER);
+ /*packageUpdatePolicy=*/ PACKAGE_UPDATE_POLICY_REFRESH_EAGER
+ | PACKAGE_RESTART_POLICY_REFRESH_EAGER);
}
@Override
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
index ca8e50aa19c9..7bd0201b997a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -1053,6 +1053,49 @@ public class AlarmManagerServiceTest {
}
}
+ @Test
+ public void nonWakeupAlarmsDeferred() throws Exception {
+ final int numAlarms = 10;
+ final PendingIntent[] pis = new PendingIntent[numAlarms];
+ for (int i = 0; i < numAlarms; i++) {
+ pis[i] = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 5, pis[i]);
+ }
+ doReturn(true).when(mService).checkAllowNonWakeupDelayLocked(anyLong());
+ // Advance time past all expirations.
+ mNowElapsedTest += numAlarms + 5;
+ mTestTimer.expire();
+ assertEquals(numAlarms, mService.mPendingNonWakeupAlarms.size());
+
+ // These alarms should be sent on interactive state change to true
+ mService.interactiveStateChangedLocked(false);
+ mService.interactiveStateChangedLocked(true);
+
+ for (int i = 0; i < numAlarms; i++) {
+ verify(pis[i]).send(eq(mMockContext), eq(0), any(Intent.class), any(),
+ any(Handler.class), isNull(), any());
+ }
+ }
+
+ @Test
+ public void alarmCountOnPendingNonWakeupAlarmsRemoved() throws Exception {
+ final int numAlarms = 10;
+ final PendingIntent[] pis = new PendingIntent[numAlarms];
+ for (int i = 0; i < numAlarms; i++) {
+ pis[i] = getNewMockPendingIntent();
+ setTestAlarm(ELAPSED_REALTIME, mNowElapsedTest + i + 5, pis[i]);
+ }
+ doReturn(true).when(mService).checkAllowNonWakeupDelayLocked(anyLong());
+ // Advance time past all expirations.
+ mNowElapsedTest += numAlarms + 5;
+ mTestTimer.expire();
+ assertEquals(numAlarms, mService.mPendingNonWakeupAlarms.size());
+ for (int i = 0; i < numAlarms; i++) {
+ mService.removeLocked(pis[i], null);
+ assertEquals(numAlarms - i - 1, mService.mAlarmsPerUid.get(TEST_CALLING_UID, 0));
+ }
+ }
+
@After
public void tearDown() {
if (mMockingSession != null) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 26230949cda6..af5a539450ac 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -72,6 +72,7 @@ import java.util.Map;
import java.util.Set;
import java.util.function.IntFunction;
import java.util.stream.Collectors;
+import java.util.concurrent.Executor;
@Presubmit
@RunWith(JUnit4.class)
@@ -91,6 +92,8 @@ public class AppsFilterTest {
AppsFilter.FeatureConfig mFeatureConfigMock;
@Mock
AppsFilter.StateProvider mStateProvider;
+ @Mock
+ Executor mMockExecutor;
private ArrayMap<String, PackageSetting> mExisting = new ArrayMap<>();
@@ -187,10 +190,15 @@ public class AppsFilterTest {
doAnswer(invocation -> {
((AppsFilter.StateProvider.CurrentStateCallback) invocation.getArgument(0))
.currentState(mExisting, USER_INFO_LIST);
- return null;
+ return new Object();
}).when(mStateProvider)
.runWithState(any(AppsFilter.StateProvider.CurrentStateCallback.class));
+ doAnswer(invocation -> {
+ ((Runnable) invocation.getArgument(0)).run();
+ return new Object();
+ }).when(mMockExecutor).execute(any(Runnable.class));
+
when(mFeatureConfigMock.isGloballyEnabled()).thenReturn(true);
when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class))).thenAnswer(
(Answer<Boolean>) invocation ->
@@ -201,7 +209,8 @@ public class AppsFilterTest {
@Test
public void testSystemReadyPropogates() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
appsFilter.onSystemReady();
verify(mFeatureConfigMock).onSystemReady();
}
@@ -209,7 +218,8 @@ public class AppsFilterTest {
@Test
public void testQueriesAction_FilterMatches() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -225,7 +235,8 @@ public class AppsFilterTest {
@Test
public void testQueriesProtectedAction_FilterDoesNotMatch() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
final Signature frameworkSignature = Mockito.mock(Signature.class);
final PackageParser.SigningDetails frameworkSigningDetails =
new PackageParser.SigningDetails(new Signature[]{frameworkSignature}, 1);
@@ -263,7 +274,8 @@ public class AppsFilterTest {
@Test
public void testQueriesProvider_FilterMatches() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -280,7 +292,8 @@ public class AppsFilterTest {
@Test
public void testQueriesDifferentProvider_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -297,7 +310,8 @@ public class AppsFilterTest {
@Test
public void testQueriesProviderWithSemiColon_FilterMatches() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -315,7 +329,8 @@ public class AppsFilterTest {
@Test
public void testQueriesAction_NoMatchingAction_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -331,7 +346,8 @@ public class AppsFilterTest {
@Test
public void testQueriesAction_NoMatchingActionFilterLowSdk_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -351,7 +367,8 @@ public class AppsFilterTest {
@Test
public void testNoQueries_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -365,14 +382,16 @@ public class AppsFilterTest {
}
@Test
- public void testForceQueryable_DoesntFilter() throws Exception {
+ public void testForceQueryable_SystemDoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
PackageSetting target = simulateAddPackage(appsFilter,
- pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_APPID);
+ pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_APPID,
+ setting -> setting.setPkgFlags(ApplicationInfo.FLAG_SYSTEM));
PackageSetting calling = simulateAddPackage(appsFilter,
pkg("com.some.other.package"), DUMMY_CALLING_APPID);
@@ -380,11 +399,29 @@ public class AppsFilterTest {
SYSTEM_USER));
}
+
+ @Test
+ public void testForceQueryable_NonSystemFilters() throws Exception {
+ final AppsFilter appsFilter =
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
+ simulateAddBasicAndroid(appsFilter);
+ appsFilter.onSystemReady();
+
+ PackageSetting target = simulateAddPackage(appsFilter,
+ pkg("com.some.package").setForceQueryable(true), DUMMY_TARGET_APPID);
+ PackageSetting calling = simulateAddPackage(appsFilter,
+ pkg("com.some.other.package"), DUMMY_CALLING_APPID);
+
+ assertTrue(appsFilter.shouldFilterApplication(DUMMY_CALLING_APPID, calling, target,
+ SYSTEM_USER));
+ }
+
@Test
public void testForceQueryableByDevice_SystemCaller_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"},
- false, null);
+ false, null, mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -402,7 +439,8 @@ public class AppsFilterTest {
@Test
public void testSystemSignedTarget_DoesntFilter() throws CertificateException {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
appsFilter.onSystemReady();
final Signature frameworkSignature = Mockito.mock(Signature.class);
@@ -431,7 +469,7 @@ public class AppsFilterTest {
public void testForceQueryableByDevice_NonSystemCaller_Filters() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{"com.some.package"},
- false, null);
+ false, null, mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -449,7 +487,7 @@ public class AppsFilterTest {
public void testSystemQueryable_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{},
- true /* system force queryable */, null);
+ true /* system force queryable */, null, mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -466,7 +504,8 @@ public class AppsFilterTest {
@Test
public void testQueriesPackage_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -484,7 +523,8 @@ public class AppsFilterTest {
when(mFeatureConfigMock.packageIsEnabled(any(AndroidPackage.class)))
.thenReturn(false);
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -500,7 +540,8 @@ public class AppsFilterTest {
@Test
public void testSystemUid_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -515,7 +556,8 @@ public class AppsFilterTest {
@Test
public void testSystemUidSecondaryUser_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -531,7 +573,8 @@ public class AppsFilterTest {
@Test
public void testNonSystemUid_NoCallingSetting_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -545,7 +588,8 @@ public class AppsFilterTest {
@Test
public void testNoTargetPackage_filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -603,7 +647,8 @@ public class AppsFilterTest {
}
return Collections.emptyMap();
}
- });
+ },
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -675,7 +720,8 @@ public class AppsFilterTest {
}
return Collections.emptyMap();
}
- });
+ },
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -700,7 +746,8 @@ public class AppsFilterTest {
@Test
public void testInitiatingApp_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -716,7 +763,8 @@ public class AppsFilterTest {
@Test
public void testUninstalledInitiatingApp_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -732,7 +780,8 @@ public class AppsFilterTest {
@Test
public void testOriginatingApp_Filters() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -748,7 +797,8 @@ public class AppsFilterTest {
@Test
public void testInstallingApp_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -764,7 +814,8 @@ public class AppsFilterTest {
@Test
public void testInstrumentation_DoesntFilter() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
@@ -786,7 +837,8 @@ public class AppsFilterTest {
@Test
public void testWhoCanSee() throws Exception {
final AppsFilter appsFilter =
- new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null);
+ new AppsFilter(mStateProvider, mFeatureConfigMock, new String[]{}, false, null,
+ mMockExecutor);
simulateAddBasicAndroid(appsFilter);
appsFilter.onSystemReady();
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
index 66ca839081bc..0ccc02663dc5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
@@ -105,7 +105,7 @@ public class UserManagerServiceUserInfoTest {
UserData read = mUserManagerService.readUserLP(
data.info.id, new ByteArrayInputStream(bytes));
- assertUserInfoEquals(data.info, read.info);
+ assertUserInfoEquals(data.info, read.info, /* parcelCopy= */ false);
}
@Test
@@ -123,7 +123,16 @@ public class UserManagerServiceUserInfoTest {
UserInfo read = UserInfo.CREATOR.createFromParcel(in);
in.recycle();
- assertUserInfoEquals(info, read);
+ assertUserInfoEquals(info, read, /* parcelCopy= */ true);
+ }
+
+ @Test
+ public void testCopyConstructor() throws Exception {
+ UserInfo info = createUser();
+
+ UserInfo copy = new UserInfo(info);
+
+ assertUserInfoEquals(info, copy, /* parcelCopy= */ false);
}
@Test
@@ -227,10 +236,11 @@ public class UserManagerServiceUserInfoTest {
user.partial = true;
user.guestToRemove = true;
user.preCreated = true;
+ user.convertedFromPreCreated = true;
return user;
}
- private void assertUserInfoEquals(UserInfo one, UserInfo two) {
+ private void assertUserInfoEquals(UserInfo one, UserInfo two, boolean parcelCopy) {
assertEquals("Id not preserved", one.id, two.id);
assertEquals("Name not preserved", one.name, two.name);
assertEquals("Icon path not preserved", one.iconPath, two.iconPath);
@@ -238,11 +248,17 @@ public class UserManagerServiceUserInfoTest {
assertEquals("UserType not preserved", one.userType, two.userType);
assertEquals("profile group not preserved", one.profileGroupId,
two.profileGroupId);
- assertEquals("restricted profile parent not preseved", one.restrictedProfileParentId,
+ assertEquals("restricted profile parent not preserved", one.restrictedProfileParentId,
two.restrictedProfileParentId);
- assertEquals("profile badge not preseved", one.profileBadge, two.profileBadge);
- assertEquals("partial not preseved", one.partial, two.partial);
- assertEquals("guestToRemove not preseved", one.guestToRemove, two.guestToRemove);
- assertEquals("preCreated not preseved", one.preCreated, two.preCreated);
+ assertEquals("profile badge not preserved", one.profileBadge, two.profileBadge);
+ assertEquals("partial not preserved", one.partial, two.partial);
+ assertEquals("guestToRemove not preserved", one.guestToRemove, two.guestToRemove);
+ assertEquals("preCreated not preserved", one.preCreated, two.preCreated);
+ if (parcelCopy) {
+ assertFalse("convertedFromPreCreated should not be set", two.convertedFromPreCreated);
+ } else {
+ assertEquals("convertedFromPreCreated not preserved", one.convertedFromPreCreated,
+ two.convertedFromPreCreated);
+ }
}
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 16aa87b3e59c..52e08187b2ca 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3865,7 +3865,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.updateUriPermissions(recordB, recordA, mContext.getPackageName(),
USER_SYSTEM);
verify(mUgmInternal, times(1)).revokeUriPermissionFromOwner(any(),
- eq(message1.getDataUri()), anyInt(), anyInt());
+ eq(message1.getDataUri()), anyInt(), anyInt(), eq(null), eq(-1));
// Update back means we grant access to first again
reset(mUgm);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 1ef0acd20835..02a3bb1f5632 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -22,7 +22,7 @@ import static android.content.pm.ActivityInfo.CONFIG_ORIENTATION;
import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
-import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
+import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
@@ -1694,7 +1694,7 @@ public class ActivityRecordTests extends ActivityTestsBase {
public void testGetLockTaskLaunchMode() {
final ActivityOptions options = ActivityOptions.makeBasic().setLockTaskEnabled(true);
mActivity.info.lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
- assertEquals(LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED,
+ assertEquals(LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED,
ActivityRecord.getLockTaskLaunchMode(mActivity.info, options));
mActivity.info.lockTaskLaunchMode = LOCK_TASK_LAUNCH_MODE_ALWAYS;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 1b42a0466cf7..e898c2573315 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -1206,19 +1206,22 @@ public class ActivityStackTests extends ActivityTestsBase {
@Test
public void testShouldSleepActivities() {
// When focused activity and keyguard is going away, we should not sleep regardless
- // of the display state
+ // of the display state, but keyguard-going-away should only take effects on default
+ // display since there is no keyguard on secondary displays (yet).
verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/,
- true /* displaySleeping */, false /* expected*/);
+ true /* displaySleeping */, true /* isDefaultDisplay */, false /* expected */);
+ verifyShouldSleepActivities(true /* focusedStack */, true /*keyguardGoingAway*/,
+ true /* displaySleeping */, false /* isDefaultDisplay */, true /* expected */);
// When not the focused stack, defer to display sleeping state.
verifyShouldSleepActivities(false /* focusedStack */, true /*keyguardGoingAway*/,
- true /* displaySleeping */, true /* expected*/);
+ true /* displaySleeping */, true /* isDefaultDisplay */, true /* expected */);
// If keyguard is going away, defer to the display sleeping state.
verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
- true /* displaySleeping */, true /* expected*/);
+ true /* displaySleeping */, true /* isDefaultDisplay */, true /* expected */);
verifyShouldSleepActivities(true /* focusedStack */, false /*keyguardGoingAway*/,
- false /* displaySleeping */, false /* expected*/);
+ false /* displaySleeping */, true /* isDefaultDisplay */, false /* expected */);
}
@Test
@@ -1428,9 +1431,11 @@ public class ActivityStackTests extends ActivityTestsBase {
}
private void verifyShouldSleepActivities(boolean focusedStack,
- boolean keyguardGoingAway, boolean displaySleeping, boolean expected) {
+ boolean keyguardGoingAway, boolean displaySleeping, boolean isDefaultDisplay,
+ boolean expected) {
final DisplayContent display = mock(DisplayContent.class);
final KeyguardController keyguardController = mSupervisor.getKeyguardController();
+ display.isDefaultDisplay = isDefaultDisplay;
doReturn(display).when(mStack).getDisplay();
doReturn(keyguardGoingAway).when(keyguardController).isKeyguardGoingAway();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index cbccfb3725e9..dc838f1bb288 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1282,7 +1282,7 @@ public class DisplayContentTests extends WindowTestsBase {
assertFalse(displayRotation.updateRotationUnchecked(false));
// Rotation can be updated if the recents animation is finished.
- mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation(false);
+ mDisplayContent.mFixedRotationTransitionListener.onFinishRecentsAnimation();
assertTrue(displayRotation.updateRotationUnchecked(false));
// Rotation can be updated if the recents animation is animating but it is not on top, e.g.
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 2f3afbcb6d72..cb9b49abfe2b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -20,6 +20,8 @@ import static android.view.Gravity.BOTTOM;
import static android.view.Gravity.LEFT;
import static android.view.Gravity.RIGHT;
import static android.view.Gravity.TOP;
+import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
+import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.InsetsState.ITYPE_TOP_GESTURES;
@@ -36,6 +38,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -197,10 +200,15 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
@Test
public void addingWindow_throwsException_WithMultipleInsetTypes() {
- WindowState win = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel");
- win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
+ WindowState win1 = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel");
+ win1.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
+
+ expectThrows(IllegalArgumentException.class, () -> addWindow(win1));
- expectThrows(IllegalArgumentException.class, () -> addWindow(win));
+ WindowState win2 = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel");
+ win2.mAttrs.providesInsetsTypes = new int[]{ITYPE_CLIMATE_BAR, ITYPE_EXTRA_NAVIGATION_BAR};
+
+ expectThrows(IllegalArgumentException.class, () -> addWindow(win2));
}
@Test
@@ -349,6 +357,24 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
}
@Test
+ public void layoutWindowLw_insetParentFrameByIme() {
+ final InsetsState state =
+ mDisplayContent.getInsetsStateController().getRawInsetsState();
+ state.getSource(InsetsState.ITYPE_IME).setVisible(true);
+ state.getSource(InsetsState.ITYPE_IME).setFrame(
+ 0, DISPLAY_HEIGHT - IME_HEIGHT, DISPLAY_WIDTH, DISPLAY_HEIGHT);
+ mWindow.mAttrs.privateFlags |= PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME;
+ mWindow.mBehindIme = true;
+ addWindow(mWindow);
+
+ mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
+ mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
+
+ assertInsetByTopBottom(mWindow.getDisplayFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
+ assertInsetByTopBottom(mWindow.getParentFrame(), STATUS_BAR_HEIGHT, IME_HEIGHT);
+ }
+
+ @Test
public void layoutWindowLw_fitDisplayCutout() {
addDisplayCutout();
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
index 7ba3fd815b2d..c87014a8a27f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
@@ -62,7 +62,7 @@ public class DisplayPolicyTestsBase extends WindowTestsBase {
static final int STATUS_BAR_HEIGHT = 10;
static final int NAV_BAR_HEIGHT = 15;
static final int DISPLAY_CUTOUT_HEIGHT = 8;
- static final int INPUT_METHOD_WINDOW_TOP = 585;
+ static final int IME_HEIGHT = 415;
DisplayPolicy mDisplayPolicy;
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index 0a27e1a1da68..73ac408f7980 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -20,6 +20,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.view.InsetsState.ITYPE_CLIMATE_BAR;
+import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
@@ -292,12 +294,17 @@ public class InsetsStateControllerTest extends WindowTestsBase {
public void testBarControllingWinChanged() {
final WindowState navBar = createWindow(null, TYPE_APPLICATION, "navBar");
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
+ final WindowState climateBar = createWindow(null, TYPE_APPLICATION, "climateBar");
+ final WindowState extraNavBar = createWindow(null, TYPE_APPLICATION, "extraNavBar");
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
+ getController().getSourceProvider(ITYPE_CLIMATE_BAR).setWindow(climateBar, null, null);
+ getController().getSourceProvider(ITYPE_EXTRA_NAVIGATION_BAR).setWindow(extraNavBar, null,
+ null);
getController().onBarControlTargetChanged(app, null, app, null);
InsetsSourceControl[] controls = getController().getControlsForDispatch(app);
- assertEquals(2, controls.length);
+ assertEquals(4, controls.length);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
index a137cde2d351..e345becf0499 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -168,8 +168,8 @@ public class LockTaskControllerTest {
@Test
public void testStartLockTaskMode_once() throws Exception {
- // GIVEN a task record with whitelisted auth
- Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ // GIVEN a task record with allowlisted auth
+ Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
// WHEN calling setLockTaskMode for LOCKED mode without resuming
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
@@ -185,9 +185,9 @@ public class LockTaskControllerTest {
@Test
public void testStartLockTaskMode_twice() throws Exception {
- // GIVEN two task records with whitelisted auth
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
- Task tr2 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ // GIVEN two task records with allowlisted auth
+ Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
// WHEN calling setLockTaskMode for LOCKED mode on both tasks
mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
@@ -205,7 +205,7 @@ public class LockTaskControllerTest {
@Test
public void testStartLockTaskMode_pinningRequest() {
- // GIVEN a task record that is not whitelisted, i.e. with pinned auth
+ // GIVEN a task record that is not allowlisted, i.e. with pinned auth
Task tr = getTask(Task.LOCK_TASK_AUTH_PINNABLE);
// WHEN calling startLockTaskMode
@@ -236,23 +236,23 @@ public class LockTaskControllerTest {
@Test
public void testLockTaskViolation() {
- // GIVEN one task record with whitelisted auth that is in lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ // GIVEN one task record with allowlisted auth that is in lock task mode
+ Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// THEN it's not a lock task violation to try and launch this task without clearing
assertFalse(mLockTaskController.isLockTaskModeViolation(tr, false));
- // THEN it's a lock task violation to launch another task that is not whitelisted
+ // THEN it's a lock task violation to launch another task that is not allowlisted
assertTrue(mLockTaskController.isLockTaskModeViolation(getTask(
Task.LOCK_TASK_AUTH_PINNABLE)));
// THEN it's a lock task violation to launch another task that is disallowed from lock task
assertTrue(mLockTaskController.isLockTaskModeViolation(getTask(
Task.LOCK_TASK_AUTH_DONT_LOCK)));
- // THEN it's no a lock task violation to launch another task that is whitelisted
+ // THEN it's no a lock task violation to launch another task that is allowlisted
assertFalse(mLockTaskController.isLockTaskModeViolation(getTask(
- Task.LOCK_TASK_AUTH_WHITELISTED)));
+ Task.LOCK_TASK_AUTH_ALLOWLISTED)));
assertFalse(mLockTaskController.isLockTaskModeViolation(getTask(
Task.LOCK_TASK_AUTH_LAUNCHABLE)));
// THEN it's not a lock task violation to launch another task that is priv launchable
@@ -262,8 +262,8 @@ public class LockTaskControllerTest {
@Test
public void testLockTaskViolation_emergencyCall() {
- // GIVEN one task record with whitelisted auth that is in lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ // GIVEN one task record with allowlisted auth that is in lock task mode
+ Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// GIVEN tasks necessary for emergency calling
@@ -294,8 +294,8 @@ public class LockTaskControllerTest {
@Test
public void testStopLockTaskMode() throws Exception {
- // GIVEN one task record with whitelisted auth that is in lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ // GIVEN one task record with allowlisted auth that is in lock task mode
+ Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// WHEN the same caller calls stopLockTaskMode
@@ -311,8 +311,8 @@ public class LockTaskControllerTest {
@Test(expected = SecurityException.class)
public void testStopLockTaskMode_differentCaller() {
- // GIVEN one task record with whitelisted auth that is in lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ // GIVEN one task record with allowlisted auth that is in lock task mode
+ Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// WHEN a different caller calls stopLockTaskMode
@@ -323,8 +323,8 @@ public class LockTaskControllerTest {
@Test
public void testStopLockTaskMode_systemCaller() {
- // GIVEN one task record with whitelisted auth that is in lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ // GIVEN one task record with allowlisted auth that is in lock task mode
+ Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// WHEN system calls stopLockTaskMode
@@ -336,9 +336,9 @@ public class LockTaskControllerTest {
@Test
public void testStopLockTaskMode_twoTasks() throws Exception {
- // GIVEN two task records with whitelisted auth that is in lock task mode
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
- Task tr2 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ // GIVEN two task records with allowlisted auth that is in lock task mode
+ Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
@@ -357,9 +357,9 @@ public class LockTaskControllerTest {
@Test
public void testStopLockTaskMode_rootTask() throws Exception {
- // GIVEN two task records with whitelisted auth that is in lock task mode
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
- Task tr2 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ // GIVEN two task records with allowlisted auth that is in lock task mode
+ Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
@@ -405,9 +405,9 @@ public class LockTaskControllerTest {
@Test
public void testClearLockedTasks() throws Exception {
- // GIVEN two task records with whitelisted auth that is in lock task mode
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
- Task tr2 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ // GIVEN two task records with allowlisted auth that is in lock task mode
+ Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
+ Task tr2 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
mLockTaskController.startLockTaskMode(tr2, false, TEST_UID);
@@ -434,7 +434,7 @@ public class LockTaskControllerTest {
.thenReturn(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
// AND there is a task record
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
// WHEN calling clearLockedTasks on the root task
@@ -454,7 +454,7 @@ public class LockTaskControllerTest {
.thenReturn(true);
// AND there is a task record
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
// WHEN calling clearLockedTasks on the root task
@@ -471,7 +471,7 @@ public class LockTaskControllerTest {
Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, 1, mContext.getUserId());
// AND there is a task record
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
// WHEN calling clearLockedTasks on the root task
@@ -488,7 +488,7 @@ public class LockTaskControllerTest {
Settings.Secure.LOCK_TO_APP_EXIT_LOCKED, 0, mContext.getUserId());
// AND there is a task record
- Task tr1 = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ Task tr1 = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr1, true, TEST_UID);
// WHEN calling clearLockedTasks on the root task
@@ -500,45 +500,45 @@ public class LockTaskControllerTest {
@Test
public void testUpdateLockTaskPackages() {
- String[] whitelist1 = {TEST_PACKAGE_NAME, TEST_PACKAGE_NAME_2};
- String[] whitelist2 = {TEST_PACKAGE_NAME};
-
- // No package is whitelisted initially
- for (String pkg : whitelist1) {
- assertFalse("Package shouldn't be whitelisted: " + pkg,
- mLockTaskController.isPackageWhitelisted(TEST_USER_ID, pkg));
- assertFalse("Package shouldn't be whitelisted for user 0: " + pkg,
- mLockTaskController.isPackageWhitelisted(0, pkg));
+ String[] allowlist1 = {TEST_PACKAGE_NAME, TEST_PACKAGE_NAME_2};
+ String[] allowlist2 = {TEST_PACKAGE_NAME};
+
+ // No package is allowlisted initially
+ for (String pkg : allowlist1) {
+ assertFalse("Package shouldn't be allowlisted: " + pkg,
+ mLockTaskController.isPackageAllowlisted(TEST_USER_ID, pkg));
+ assertFalse("Package shouldn't be allowlisted for user 0: " + pkg,
+ mLockTaskController.isPackageAllowlisted(0, pkg));
}
- // Apply whitelist
- mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist1);
+ // Apply allowlist
+ mLockTaskController.updateLockTaskPackages(TEST_USER_ID, allowlist1);
- // Assert the whitelist is applied to the correct user
- for (String pkg : whitelist1) {
- assertTrue("Package should be whitelisted: " + pkg,
- mLockTaskController.isPackageWhitelisted(TEST_USER_ID, pkg));
- assertFalse("Package shouldn't be whitelisted for user 0: " + pkg,
- mLockTaskController.isPackageWhitelisted(0, pkg));
+ // Assert the allowlist is applied to the correct user
+ for (String pkg : allowlist1) {
+ assertTrue("Package should be allowlisted: " + pkg,
+ mLockTaskController.isPackageAllowlisted(TEST_USER_ID, pkg));
+ assertFalse("Package shouldn't be allowlisted for user 0: " + pkg,
+ mLockTaskController.isPackageAllowlisted(0, pkg));
}
- // Update whitelist
- mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist2);
+ // Update allowlist
+ mLockTaskController.updateLockTaskPackages(TEST_USER_ID, allowlist2);
- // Assert the new whitelist is applied
- assertTrue("Package should remain whitelisted: " + TEST_PACKAGE_NAME,
- mLockTaskController.isPackageWhitelisted(TEST_USER_ID, TEST_PACKAGE_NAME));
- assertFalse("Package should no longer be whitelisted: " + TEST_PACKAGE_NAME_2,
- mLockTaskController.isPackageWhitelisted(TEST_USER_ID, TEST_PACKAGE_NAME_2));
+ // Assert the new allowlist is applied
+ assertTrue("Package should remain allowlisted: " + TEST_PACKAGE_NAME,
+ mLockTaskController.isPackageAllowlisted(TEST_USER_ID, TEST_PACKAGE_NAME));
+ assertFalse("Package should no longer be allowlisted: " + TEST_PACKAGE_NAME_2,
+ mLockTaskController.isPackageAllowlisted(TEST_USER_ID, TEST_PACKAGE_NAME_2));
}
@Test
public void testUpdateLockTaskPackages_taskRemoved() throws Exception {
- // GIVEN two tasks which are whitelisted initially
+ // GIVEN two tasks which are allowlisted initially
Task tr1 = getTaskForUpdate(TEST_PACKAGE_NAME, true);
Task tr2 = getTaskForUpdate(TEST_PACKAGE_NAME_2, false);
- String[] whitelist = {TEST_PACKAGE_NAME, TEST_PACKAGE_NAME_2};
- mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);
+ String[] allowlist = {TEST_PACKAGE_NAME, TEST_PACKAGE_NAME_2};
+ mLockTaskController.updateLockTaskPackages(TEST_USER_ID, allowlist);
// GIVEN the tasks are launched into LockTask mode
mLockTaskController.startLockTaskMode(tr1, false, TEST_UID);
@@ -548,9 +548,9 @@ public class LockTaskControllerTest {
assertTrue(mLockTaskController.isTaskLocked(tr2));
verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);
- // WHEN removing one package from whitelist
- whitelist = new String[] {TEST_PACKAGE_NAME};
- mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);
+ // WHEN removing one package from allowlist
+ allowlist = new String[] {TEST_PACKAGE_NAME};
+ mLockTaskController.updateLockTaskPackages(TEST_USER_ID, allowlist);
// THEN the task running that package should be stopped
verify(tr2).performClearTaskLocked();
@@ -560,9 +560,9 @@ public class LockTaskControllerTest {
assertTrue(mLockTaskController.isTaskLocked(tr1));
verifyLockTaskStarted(STATUS_BAR_MASK_LOCKED, DISABLE2_MASK);
- // WHEN removing the last package from whitelist
- whitelist = new String[] {};
- mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);
+ // WHEN removing the last package from allowlist
+ allowlist = new String[] {};
+ mLockTaskController.updateLockTaskPackages(TEST_USER_ID, allowlist);
// THEN the last task should be cleared, and the system should quit LockTask mode
verify(tr1).performClearTaskLocked();
@@ -574,7 +574,7 @@ public class LockTaskControllerTest {
@Test
public void testUpdateLockTaskFeatures() throws Exception {
// GIVEN a locked task
- Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// THEN lock task mode should be started with default status bar masks
@@ -616,7 +616,7 @@ public class LockTaskControllerTest {
@Test
public void testUpdateLockTaskFeatures_differentUser() throws Exception {
// GIVEN a locked task
- Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// THEN lock task mode should be started with default status bar masks
@@ -638,7 +638,7 @@ public class LockTaskControllerTest {
@Test
public void testUpdateLockTaskFeatures_keyguard() {
// GIVEN a locked task
- Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// THEN keyguard should be disabled
@@ -704,7 +704,7 @@ public class LockTaskControllerTest {
TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT));
// Start lock task mode
- Task tr = getTask(Task.LOCK_TASK_AUTH_WHITELISTED);
+ Task tr = getTask(Task.LOCK_TASK_AUTH_ALLOWLISTED);
mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
// WHEN LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK is not enabled
@@ -719,15 +719,15 @@ public class LockTaskControllerTest {
assertTrue(mLockTaskController.isActivityAllowed(
TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_ALWAYS));
- // unwhitelisted package should not be allowed
+ // unallowlisted package should not be allowed
assertFalse(mLockTaskController.isActivityAllowed(
TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT));
- // update the whitelist
- String[] whitelist = new String[] { TEST_PACKAGE_NAME };
- mLockTaskController.updateLockTaskPackages(TEST_USER_ID, whitelist);
+ // update the allowlist
+ String[] allowlist = new String[] { TEST_PACKAGE_NAME };
+ mLockTaskController.updateLockTaskPackages(TEST_USER_ID, allowlist);
- // whitelisted package should be allowed
+ // allowlisted package should be allowed
assertTrue(mLockTaskController.isActivityAllowed(
TEST_USER_ID, TEST_PACKAGE_NAME, LOCK_TASK_LAUNCH_MODE_DEFAULT));
@@ -755,17 +755,17 @@ public class LockTaskControllerTest {
}
/**
- * @param isAppAware {@code true} if the app has marked if_whitelisted in its manifest
+ * @param isAppAware {@code true} if the app has marked if_allowlisted in its manifest
*/
private Task getTaskForUpdate(String pkg, boolean isAppAware) {
- final int authIfWhitelisted = isAppAware
+ final int authIfAllowlisted = isAppAware
? Task.LOCK_TASK_AUTH_LAUNCHABLE
- : Task.LOCK_TASK_AUTH_WHITELISTED;
- Task tr = getTask(pkg, authIfWhitelisted);
+ : Task.LOCK_TASK_AUTH_ALLOWLISTED;
+ Task tr = getTask(pkg, authIfAllowlisted);
doAnswer((invocation) -> {
- boolean isWhitelisted =
- mLockTaskController.isPackageWhitelisted(TEST_USER_ID, pkg);
- tr.mLockTaskAuth = isWhitelisted ? authIfWhitelisted : Task.LOCK_TASK_AUTH_PINNABLE;
+ boolean isAllowlisted =
+ mLockTaskController.isPackageAllowlisted(TEST_USER_ID, pkg);
+ tr.mLockTaskAuth = isAllowlisted ? authIfAllowlisted : Task.LOCK_TASK_AUTH_PINNABLE;
return null;
}).when(tr).setLockTaskAuth();
return tr;
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 8e85e7b96d1f..f2771175b523 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -363,12 +363,14 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
assertFalse(homeActivity.hasFixedRotationTransform());
}
- @Test
- public void testClearFixedRotationLaunchingAppAfterCleanupAnimation() {
+ private ActivityRecord prepareFixedRotationLaunchingAppWithRecentsAnim() {
final ActivityRecord homeActivity = createHomeActivity();
homeActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+ // Add a window so it can be animated by the recents.
+ final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, activity, "win");
+ activity.addWindow(win);
// Assume an activity is launching to different rotation.
mDefaultDisplay.setFixedRotationLaunchingApp(activity,
(mDefaultDisplay.getRotation() + 1) % 4);
@@ -379,6 +381,14 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
// Before the transition is done, the recents animation is triggered.
initializeRecentsAnimationController(mController, homeActivity);
assertFalse(homeActivity.hasFixedRotationTransform());
+ assertTrue(mController.isAnimatingTask(activity.getTask()));
+
+ return activity;
+ }
+
+ @Test
+ public void testClearFixedRotationLaunchingAppAfterCleanupAnimation() {
+ final ActivityRecord activity = prepareFixedRotationLaunchingAppWithRecentsAnim();
// Simulate giving up the swipe up gesture to keep the original activity as top.
mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
@@ -388,6 +398,21 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
}
@Test
+ public void testKeepFixedRotationWhenMovingRecentsToTop() {
+ final ActivityRecord activity = prepareFixedRotationLaunchingAppWithRecentsAnim();
+ // Assume a transition animation has started running before recents animation. Then the
+ // activity will receive onAnimationFinished that notifies app transition finished when
+ // removing the recents animation of task.
+ activity.getTask().getAnimationSources().add(activity);
+
+ // Simulate swiping to home/recents before the transition is done.
+ mController.cleanupAnimation(REORDER_MOVE_TO_TOP);
+ // The rotation transform should be preserved. In real case, it will be cleared by the next
+ // move-to-top transition.
+ assertTrue(activity.hasFixedRotationTransform());
+ }
+
+ @Test
public void testWallpaperHasFixedRotationApplied() {
mWm.setRecentsAnimationController(mController);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index c848736a64c2..51db099676b0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -896,24 +896,6 @@ public class RootActivityContainerTests extends ActivityTestsBase {
assertEquals(taskDisplayArea.getTopStack(), taskDisplayArea.getRootHomeTask());
}
- @Test
- public void testResumeFocusedStackOnSleepingDisplay() {
- // Create an activity on secondary display.
- final TestDisplayContent secondDisplay = addNewDisplayContentAt(
- DisplayContent.POSITION_TOP);
- final ActivityStack stack = secondDisplay.getDefaultTaskDisplayArea()
- .createStack(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, true /* onTop */);
- final ActivityRecord activity = new ActivityBuilder(mService).setStack(stack).build();
- spyOn(activity);
- spyOn(stack);
-
- // Cannot resumed activities on secondary display if the display should sleep.
- doReturn(true).when(secondDisplay).shouldSleep();
- mRootWindowContainer.resumeFocusedStacksTopActivities();
- verify(stack, never()).resumeTopActivityUncheckedLocked(any(), any());
- verify(activity, never()).makeActiveIfNeeded(any());
- }
-
/**
* Mock {@link RootWindowContainer#resolveHomeActivity} for returning consistent activity
* info for test cases.
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
index 23a097eb0c7c..0896db4b5532 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTokenTests.java
@@ -24,6 +24,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@@ -139,6 +140,8 @@ public class WindowTokenTests extends WindowTestsBase {
public void testFinishFixedRotationTransform() {
final WindowToken appToken = mAppWindow.mToken;
final WindowToken wallpaperToken = mWallpaperWindow.mToken;
+ final WindowToken testToken =
+ WindowTestUtils.createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDisplayContent);
final Configuration config = new Configuration(mDisplayContent.getConfiguration());
final int originalRotation = config.windowConfiguration.getRotation();
final int targetRotation = (originalRotation + 1) % 4;
@@ -151,11 +154,20 @@ public class WindowTokenTests extends WindowTestsBase {
assertEquals(targetRotation, appToken.getWindowConfiguration().getRotation());
assertEquals(targetRotation, wallpaperToken.getWindowConfiguration().getRotation());
- // The display doesn't rotate, the transformation will be canceled.
- mAppWindow.mToken.finishFixedRotationTransform();
+ testToken.applyFixedRotationTransform(mDisplayInfo, mDisplayContent.mDisplayFrames, config);
+ // The wallpaperToken was linked to appToken, this should make it link to testToken.
+ wallpaperToken.linkFixedRotationTransform(testToken);
- // The window tokens should restore to the original rotation.
+ // Assume the display doesn't rotate, the transformation will be canceled.
+ appToken.finishFixedRotationTransform();
+
+ // The appToken should restore to the original rotation.
assertEquals(originalRotation, appToken.getWindowConfiguration().getRotation());
+ // The wallpaperToken is linked to testToken, it should keep the target rotation.
+ assertNotEquals(originalRotation, wallpaperToken.getWindowConfiguration().getRotation());
+
+ testToken.finishFixedRotationTransform();
+ // The rotation of wallpaperToken should be restored because its linked state is finished.
assertEquals(originalRotation, wallpaperToken.getWindowConfiguration().getRotation());
}
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 6c13cd799bc2..fe0f7b80997e 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -697,7 +697,7 @@ public class SoundTriggerService extends SystemService {
synchronized (mLock) {
ModuleProperties properties = mSoundTriggerHelper.getModuleProperties();
sEventLogger.log(new SoundTriggerLogger.StringEvent(
- "getModuleProperties(): " + properties.toString()));
+ "getModuleProperties(): " + properties));
return properties;
}
}
@@ -1284,32 +1284,25 @@ public class SoundTriggerService extends SystemService {
* @return The initialized AudioRecord
*/
private @NonNull AudioRecord createAudioRecordForEvent(
- @NonNull SoundTrigger.GenericRecognitionEvent event) {
+ @NonNull SoundTrigger.GenericRecognitionEvent event)
+ throws IllegalArgumentException, UnsupportedOperationException {
AudioAttributes.Builder attributesBuilder = new AudioAttributes.Builder();
attributesBuilder.setInternalCapturePreset(MediaRecorder.AudioSource.HOTWORD);
AudioAttributes attributes = attributesBuilder.build();
- // Use same AudioFormat processing as in RecognitionEvent.fromParcel
AudioFormat originalFormat = event.getCaptureFormat();
- AudioFormat captureFormat = (new AudioFormat.Builder())
- .setChannelMask(originalFormat.getChannelMask())
- .setEncoding(originalFormat.getEncoding())
- .setSampleRate(originalFormat.getSampleRate())
- .build();
-
- int bufferSize = AudioRecord.getMinBufferSize(
- captureFormat.getSampleRate() == AudioFormat.SAMPLE_RATE_UNSPECIFIED
- ? AudioFormat.SAMPLE_RATE_HZ_MAX
- : captureFormat.getSampleRate(),
- captureFormat.getChannelCount() == 2
- ? AudioFormat.CHANNEL_IN_STEREO
- : AudioFormat.CHANNEL_IN_MONO,
- captureFormat.getEncoding());
sEventLogger.log(new SoundTriggerLogger.StringEvent("createAudioRecordForEvent"));
- return new AudioRecord(attributes, captureFormat, bufferSize,
- event.getCaptureSession());
+ return (new AudioRecord.Builder())
+ .setAudioAttributes(attributes)
+ .setAudioFormat((new AudioFormat.Builder())
+ .setChannelMask(originalFormat.getChannelMask())
+ .setEncoding(originalFormat.getEncoding())
+ .setSampleRate(originalFormat.getSampleRate())
+ .build())
+ .setSessionId(event.getCaptureSession())
+ .build();
}
@Override
@@ -1335,12 +1328,16 @@ public class SoundTriggerService extends SystemService {
// execute if throttled:
() -> {
if (event.isCaptureAvailable()) {
- AudioRecord capturedData = createAudioRecordForEvent(event);
-
- // Currently we need to start and release the audio record to reset
- // the DSP even if we don't want to process the event
- capturedData.startRecording();
- capturedData.release();
+ try {
+ // Currently we need to start and release the audio record to reset
+ // the DSP even if we don't want to process the eve
+ AudioRecord capturedData = createAudioRecordForEvent(event);
+ capturedData.startRecording();
+ capturedData.release();
+ } catch (IllegalArgumentException | UnsupportedOperationException e) {
+ Slog.w(TAG, mPuuid + ": createAudioRecordForEvent(" + event
+ + "), failed to create AudioRecord");
+ }
}
}));
}
diff --git a/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl b/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl
new file mode 100644
index 000000000000..50bbf4c41284
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/IDeviceIdleControllerAdapter.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.internal.telecom;
+
+/*
+ * Adapter interface for using DeviceIdleController, since the PowerWhitelistManager is not
+ * directly accessible in the SYSTEM process.
+ */
+interface IDeviceIdleControllerAdapter {
+ void exemptAppTemporarilyForEvent(String packageName, long duration, int userHandle,
+ String reason);
+} \ No newline at end of file
diff --git a/telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl b/telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl
new file mode 100644
index 000000000000..b56010696361
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/IInternalServiceRetriever.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.internal.telecom;
+
+import com.android.internal.telecom.IDeviceIdleControllerAdapter;
+
+/*
+ * Interface used to retrieve services that are only accessible via LocalService in the SYSTEM
+ * process.
+ */
+interface IInternalServiceRetriever {
+ IDeviceIdleControllerAdapter getDeviceIdleController();
+}
diff --git a/telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl b/telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl
new file mode 100644
index 000000000000..eda0f5b24958
--- /dev/null
+++ b/telecomm/java/com/android/internal/telecom/ITelecomLoader.aidl
@@ -0,0 +1,28 @@
+/*
+ * 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.internal.telecom;
+
+import com.android.internal.telecom.ITelecomService;
+import com.android.internal.telecom.IInternalServiceRetriever;
+
+/*
+ * Internal interface for getting an instance of the ITelecomService for external publication.
+ * Allows the TelecomLoaderService to pass additional dependencies required for creation.
+ */
+interface ITelecomLoader {
+ ITelecomService createTelecomService(IInternalServiceRetriever retriever);
+}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 52f1e37e69f4..2795f939d230 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -32,6 +32,7 @@ import android.os.RemoteException;
import android.service.carrier.CarrierService;
import android.telecom.TelecomManager;
import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsSsData;
import com.android.internal.telephony.ICarrierConfigLoader;
import com.android.telephony.Rlog;
@@ -66,6 +67,20 @@ public class CarrierConfigManager {
public static final String EXTRA_SUBSCRIPTION_INDEX =
SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX;
+ /**
+ * Service class flag if not specify a service class.
+ * Reference: 3GPP TS 27.007 Section 7.4 Facility lock +CLCK
+ * @hide
+ */
+ public static final int SERVICE_CLASS_NONE = ImsSsData.SERVICE_CLASS_NONE;
+
+ /**
+ * Service class flag for voice telephony.
+ * Reference: 3GPP TS 27.007 Section 7.4 Facility lock +CLCK
+ * @hide
+ */
+ public static final int SERVICE_CLASS_VOICE = ImsSsData.SERVICE_CLASS_VOICE;
+
private final Context mContext;
/**
@@ -212,6 +227,19 @@ public class CarrierConfigManager {
"call_barring_supports_deactivate_all_bool";
/**
+ * Specifies the service class for call barring service. Default value is
+ * {@link #SERVICE_CLASS_VOICE}.
+ * The value set as below:
+ * <ul>
+ * <li>0: {@link #SERVICE_CLASS_NONE}</li>
+ * <li>1: {@link #SERVICE_CLASS_VOICE}</li>
+ * </ul>
+ * @hide
+ */
+ public static final String KEY_CALL_BARRING_DEFAULT_SERVICE_CLASS_INT =
+ "call_barring_default_service_class_int";
+
+ /**
* Flag indicating whether the Phone app should ignore EVENT_SIM_NETWORK_LOCKED
* events from the Sim.
* If true, this will prevent the IccNetworkDepersonalizationPanel from being shown, and
@@ -1642,6 +1670,15 @@ public class CarrierConfigManager {
"hide_lte_plus_data_icon_bool";
/**
+ * The combined channel bandwidth threshold (non-inclusive) in KHz required to display the
+ * LTE+ data icon. It is 20000 by default, meaning the LTE+ icon will be shown if the device is
+ * using carrier aggregation and the combined channel bandwidth is strictly greater than 20 MHz.
+ * @hide
+ */
+ public static final String KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT =
+ "lte_plus_threshold_bandwidth_khz_int";
+
+ /**
* The string is used to filter redundant string from PLMN Network Name that's supplied by
* specific carrier.
*
@@ -3840,10 +3877,23 @@ public class CarrierConfigManager {
* Indicating whether DUN APN should be disabled when the device is roaming. In that case,
* the default APN (i.e. internet) will be used for tethering.
*
+ * This config is only available when using Preset APN(not user edited) as Preferred APN.
+ *
+ * @hide
+ */
+ public static final String KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL =
+ "disable_dun_apn_while_roaming_with_preset_apn_bool";
+
+ /**
+ * Where there is no preferred APN, specifies the carrier's default preferred APN.
+ * Specifies the {@link android.provider.Telephony.Carriers.APN} of the default preferred apn.
+ *
+ * This config is only available with Preset APN(not user edited).
+ *
* @hide
*/
- public static final String KEY_DISABLE_DUN_APN_WHILE_ROAMING =
- "disable_dun_apn_while_roaming";
+ public static final String KEY_DEFAULT_PREFERRED_APN_NAME_STRING =
+ "default_preferred_apn_name_string";
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -3917,6 +3967,7 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_CALL_BARRING_VISIBILITY_BOOL, false);
sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_PASSWORD_CHANGE_BOOL, true);
sDefaults.putBoolean(KEY_CALL_BARRING_SUPPORTS_DEACTIVATE_ALL_BOOL, true);
+ sDefaults.putInt(KEY_CALL_BARRING_DEFAULT_SERVICE_CLASS_INT, SERVICE_CLASS_VOICE);
sDefaults.putBoolean(KEY_CALL_FORWARDING_VISIBILITY_BOOL, true);
sDefaults.putBoolean(KEY_CALL_FORWARDING_WHEN_UNREACHABLE_SUPPORTED_BOOL, true);
sDefaults.putBoolean(KEY_CALL_FORWARDING_WHEN_UNANSWERED_SUPPORTED_BOOL, true);
@@ -4211,6 +4262,7 @@ public class CarrierConfigManager {
sDefaults.putString(KEY_OPERATOR_NAME_FILTER_PATTERN_STRING, "");
sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, "");
sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true);
+ sDefaults.putInt(KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 20000);
sDefaults.putBoolean(KEY_NR_ENABLED_BOOL, true);
sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
sDefaults.putBoolean(KEY_SUPPORT_TDSCDMA_BOOL, false);
@@ -4378,7 +4430,8 @@ public class CarrierConfigManager {
"ims:2", "cbs:2", "ia:2", "emergency:2", "mcx:3", "xcap:3"
});
sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]);
- sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING, false);
+ sDefaults.putBoolean(KEY_DISABLE_DUN_APN_WHILE_ROAMING_WITH_PRESET_APN_BOOL, false);
+ sDefaults.putString(KEY_DEFAULT_PREFERRED_APN_NAME_STRING, "");
}
/**
diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java
index 26c8d7991b5e..45a67b39ea55 100644
--- a/telephony/java/android/telephony/CellIdentityNr.java
+++ b/telephony/java/android/telephony/CellIdentityNr.java
@@ -50,6 +50,18 @@ public final class CellIdentityNr extends CellIdentity {
// a list of additional PLMN-IDs reported for this cell
private final ArraySet<String> mAdditionalPlmns;
+ /** @hide */
+ public CellIdentityNr() {
+ super(TAG, CellInfo.TYPE_NR, null, null, null, null);
+ mNrArfcn = CellInfo.UNAVAILABLE;
+ mPci = CellInfo.UNAVAILABLE;
+ mTac = CellInfo.UNAVAILABLE;
+ mNci = CellInfo.UNAVAILABLE;
+ mBands = new int[] {};
+ mAdditionalPlmns = new ArraySet();
+ mGlobalCellId = null;
+ }
+
/**
*
* @param pci Physical Cell Id in range [0, 1007].
diff --git a/telephony/java/android/telephony/CellInfoNr.java b/telephony/java/android/telephony/CellInfoNr.java
index a7e79f93ae89..e01e8f0d5b51 100644
--- a/telephony/java/android/telephony/CellInfoNr.java
+++ b/telephony/java/android/telephony/CellInfoNr.java
@@ -29,9 +29,16 @@ import java.util.Objects;
public final class CellInfoNr extends CellInfo {
private static final String TAG = "CellInfoNr";
- private final CellIdentityNr mCellIdentity;
+ private CellIdentityNr mCellIdentity;
private final CellSignalStrengthNr mCellSignalStrength;
+ /** @hide */
+ public CellInfoNr() {
+ super();
+ mCellIdentity = new CellIdentityNr();
+ mCellSignalStrength = new CellSignalStrengthNr();
+ }
+
private CellInfoNr(Parcel in) {
super(in);
mCellIdentity = CellIdentityNr.CREATOR.createFromParcel(in);
@@ -71,6 +78,11 @@ public final class CellInfoNr extends CellInfo {
return mCellIdentity;
}
+ /** @hide */
+ public void setCellIdentity(CellIdentityNr cid) {
+ mCellIdentity = cid;
+ }
+
/**
* @return a {@link CellSignalStrengthNr} instance.
*/
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 2be4ae6bb214..3ccbad84f2e0 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -48,6 +48,9 @@ java_test_host {
name: "MultiUserRollbackTest",
srcs: ["MultiUserRollbackTest/src/**/*.java"],
libs: ["tradefed"],
+ static_libs: [
+ "frameworks-base-hostutils",
+ ],
test_suites: ["general-tests"],
test_config: "MultiUserRollbackTest.xml",
}
diff --git a/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java b/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java
index 42b886f0774f..f16084744853 100644
--- a/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java
+++ b/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java
@@ -24,6 +24,7 @@ import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -40,6 +41,9 @@ public class MultiUserRollbackTest extends BaseHostJUnit4Test {
private static final long SWITCH_USER_COMPLETED_NUMBER_OF_POLLS = 60;
private static final long SWITCH_USER_COMPLETED_POLL_INTERVAL_IN_MILLIS = 1000;
+ @Rule
+ public AbandonSessionsRule mHostTestRule = new AbandonSessionsRule(this);
+
@After
public void tearDown() throws Exception {
removeSecondaryUserIfNecessary();
@@ -59,6 +63,30 @@ public class MultiUserRollbackTest extends BaseHostJUnit4Test {
runPhaseForUsers("testBasic", mSecondaryUserId);
}
+ /**
+ * Tests staged install/rollback works correctly on the 2nd user.
+ */
+ @Test
+ public void testStagedRollback() throws Exception {
+ runPhaseForUsers("testStagedRollback_Phase1", mSecondaryUserId);
+ getDevice().reboot();
+
+ // Need to unlock the user for device tests to run successfully
+ getDevice().startUser(mSecondaryUserId);
+ awaitUserUnlocked(mSecondaryUserId);
+ runPhaseForUsers("testStagedRollback_Phase2", mSecondaryUserId);
+ getDevice().reboot();
+
+ getDevice().startUser(mSecondaryUserId);
+ awaitUserUnlocked(mSecondaryUserId);
+ runPhaseForUsers("testStagedRollback_Phase3", mSecondaryUserId);
+ getDevice().reboot();
+
+ getDevice().startUser(mSecondaryUserId);
+ awaitUserUnlocked(mSecondaryUserId);
+ runPhaseForUsers("testStagedRollback_Phase4", mSecondaryUserId);
+ }
+
@Test
public void testMultipleUsers() throws Exception {
runPhaseForUsers("testMultipleUsersInstallV1", mOriginalUserId, mSecondaryUserId);
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java
index 8641f4d4013a..5d133a4de13d 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java
@@ -115,4 +115,32 @@ public class MultiUserRollbackTest {
assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
InstallUtils.processUserData(TestApp.A);
}
+
+ @Test
+ public void testStagedRollback_Phase1() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
+ Install.single(TestApp.A1).setStaged().commit();
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1);
+ }
+
+ @Test
+ public void testStagedRollback_Phase2() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+ Install.single(TestApp.A2).setStaged().setEnableRollback().commit();
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+ }
+
+ @Test
+ public void testStagedRollback_Phase3() throws Exception {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
+ RollbackInfo rollback = RollbackUtils.waitForAvailableRollback(TestApp.A);
+ assertThat(rollback).packagesContainsExactly(Rollback.from(TestApp.A2).to(TestApp.A1));
+ RollbackUtils.rollback(rollback.getRollbackId());
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
+ }
+
+ @Test
+ public void testStagedRollback_Phase4() {
+ assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
+ }
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
index c91dfecf041b..7726c6637e0a 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsSubscriptionsMonitorTest.java
@@ -29,6 +29,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.net.NetworkTemplate;
import android.os.Looper;
@@ -135,6 +136,11 @@ public final class NetworkStatsSubscriptionsMonitorTest {
mMonitor.onSubscriptionsChanged();
}
+ private void updateSubscriberIdForTestSub(int subId, @Nullable final String subscriberId) {
+ when(mTelephonyManager.getSubscriberId(subId)).thenReturn(subscriberId);
+ mMonitor.onSubscriptionsChanged();
+ }
+
private void removeTestSub(int subId) {
// Remove subId from TestSubList.
mTestSubList.removeIf(it -> it == subId);
@@ -268,4 +274,54 @@ public final class NetworkStatsSubscriptionsMonitorTest {
listener.onServiceStateChanged(serviceState);
assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_NR);
}
+
+ @Test
+ public void testSubscriberIdUnavailable() {
+ final ArgumentCaptor<RatTypeListener> ratTypeListenerCaptor =
+ ArgumentCaptor.forClass(RatTypeListener.class);
+
+ mMonitor.start();
+ // Insert sim1, set subscriberId to null which is normal in SIM PIN locked case.
+ // Verify RAT type is NETWORK_TYPE_UNKNOWN and service will not perform listener
+ // registration.
+ addTestSub(TEST_SUBID1, null);
+ verify(mTelephonyManager, never()).listen(any(), anyInt());
+ assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
+
+ // Set IMSI for sim1, verify the listener will be registered.
+ updateSubscriberIdForTestSub(TEST_SUBID1, TEST_IMSI1);
+ verify(mTelephonyManager, times(1)).listen(ratTypeListenerCaptor.capture(),
+ eq(PhoneStateListener.LISTEN_SERVICE_STATE));
+ reset(mTelephonyManager);
+ when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
+
+ // Set RAT type of sim1 to UMTS. Verify RAT type of sim1 is changed.
+ setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
+ TelephonyManager.NETWORK_TYPE_UMTS);
+ assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
+ reset(mDelegate);
+
+ // Set IMSI to null again to simulate somehow IMSI is not available, such as
+ // modem crash. Verify service should not unregister listener.
+ updateSubscriberIdForTestSub(TEST_SUBID1, null);
+ verify(mTelephonyManager, never()).listen(any(), anyInt());
+ assertRatTypeNotChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UMTS);
+ reset(mDelegate);
+
+ // Set RAT type of sim1 to LTE. Verify RAT type of sim1 is still changed even if the IMSI
+ // is not available. The monitor keeps the listener even if the IMSI disappears because
+ // the IMSI can never change for any given subId, therefore even if the IMSI is updated
+ // to null, the monitor should continue accepting updates of the RAT type. However,
+ // telephony is never actually supposed to do this, if the IMSI disappears there should
+ // not be updates, but it's still the right thing to do theoretically.
+ setRatTypeForSub(ratTypeListenerCaptor.getAllValues(), TEST_SUBID1,
+ TelephonyManager.NETWORK_TYPE_LTE);
+ assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_LTE);
+ reset(mDelegate);
+
+ mMonitor.stop();
+ verify(mTelephonyManager, times(1)).listen(eq(ratTypeListenerCaptor.getValue()),
+ eq(PhoneStateListener.LISTEN_NONE));
+ assertRatTypeChangedForSub(TEST_IMSI1, TelephonyManager.NETWORK_TYPE_UNKNOWN);
+ }
}
diff --git a/tests/utils/hostutils/src/com/android/tests/rollback/host/AbandonSessionsRule.java b/tests/utils/hostutils/src/com/android/tests/rollback/host/AbandonSessionsRule.java
new file mode 100644
index 000000000000..5bfc75203ae3
--- /dev/null
+++ b/tests/utils/hostutils/src/com/android/tests/rollback/host/AbandonSessionsRule.java
@@ -0,0 +1,66 @@
+/*
+ * 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.tests.rollback.host;
+
+import com.android.ddmlib.Log;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+
+import org.junit.rules.ExternalResource;
+
+public final class AbandonSessionsRule extends ExternalResource {
+ private static final String TAG = "AbandonSessionsRule";
+ private final BaseHostJUnit4Test mHost;
+
+ public AbandonSessionsRule(BaseHostJUnit4Test host) {
+ mHost = host;
+ }
+
+ @Override
+ protected void before() throws Throwable {
+ abandonSessions(mHost.getDevice());
+ }
+
+ @Override
+ protected void after() {
+ try {
+ abandonSessions(mHost.getDevice());
+ } catch (Exception e) {
+ mHost.getDevice().logOnDevice(TAG, Log.LogLevel.ERROR,
+ "%s", "Failed to abandon sessions");
+ }
+ }
+
+ /**
+ * Abandons all sessions to prevent interference in our tests.
+ */
+ private static void abandonSessions(ITestDevice device) throws Exception {
+ // No point in abandoning applied or failed sessions. We care about ready sessions only.
+ String cmdListReadySessions =
+ "pm list staged-sessions --only-sessionid --only-parent --only-ready";
+ String output = device.executeShellCommand(cmdListReadySessions);
+ if (output.trim().isEmpty()) {
+ // No sessions to abandon
+ return;
+ }
+ // Ensure we have sufficient privilege to abandon sessions from other apps
+ device.enableAdbRoot();
+ device.executeShellCommand("for i in $(" + cmdListReadySessions
+ + "); do pm install-abandon $i; done");
+ device.disableAdbRoot();
+ }
+}
diff --git a/wifi/java/android/net/wifi/ScanResult.java b/wifi/java/android/net/wifi/ScanResult.java
index aa3a13925894..b276f2ed4761 100644
--- a/wifi/java/android/net/wifi/ScanResult.java
+++ b/wifi/java/android/net/wifi/ScanResult.java
@@ -581,12 +581,18 @@ public final class ScanResult implements Parcelable {
* 6 GHz band frequency of first channel in MHz
* @hide
*/
- public static final int BAND_6_GHZ_START_FREQ_MHZ = 5945;
+ public static final int BAND_6_GHZ_START_FREQ_MHZ = 5955;
/**
* 6 GHz band frequency of last channel in MHz
* @hide
*/
- public static final int BAND_6_GHZ_END_FREQ_MHZ = 7105;
+ public static final int BAND_6_GHZ_END_FREQ_MHZ = 7115;
+
+ /**
+ * 6 GHz band operating class 136 channel 2 center frequency in MHz
+ * @hide
+ */
+ public static final int BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ = 5935;
/**
* Utility function to check if a frequency within 2.4 GHz band
@@ -618,7 +624,10 @@ public final class ScanResult implements Parcelable {
* @hide
*/
public static boolean is6GHz(int freqMhz) {
- return freqMhz >= BAND_6_GHZ_START_FREQ_MHZ && freqMhz <= BAND_6_GHZ_END_FREQ_MHZ;
+ if (freqMhz == BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ) {
+ return true;
+ }
+ return (freqMhz >= BAND_6_GHZ_START_FREQ_MHZ && freqMhz <= BAND_6_GHZ_END_FREQ_MHZ);
}
/**
@@ -649,6 +658,9 @@ public final class ScanResult implements Parcelable {
}
if (band == WifiScanner.WIFI_BAND_6_GHZ) {
if (channel >= BAND_6_GHZ_FIRST_CH_NUM && channel <= BAND_6_GHZ_LAST_CH_NUM) {
+ if (channel == 2) {
+ return BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ;
+ }
return ((channel - BAND_6_GHZ_FIRST_CH_NUM) * 5) + BAND_6_GHZ_START_FREQ_MHZ;
} else {
return UNSPECIFIED;
@@ -673,6 +685,9 @@ public final class ScanResult implements Parcelable {
} else if (is5GHz(freqMhz)) {
return ((freqMhz - BAND_5_GHZ_START_FREQ_MHZ) / 5) + BAND_5_GHZ_FIRST_CH_NUM;
} else if (is6GHz(freqMhz)) {
+ if (freqMhz == BAND_6_GHZ_OP_CLASS_136_CH_2_FREQ_MHZ) {
+ return 2;
+ }
return ((freqMhz - BAND_6_GHZ_START_FREQ_MHZ) / 5) + BAND_6_GHZ_FIRST_CH_NUM;
}
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 77fa673f1960..90edc4523b7b 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -30,6 +30,9 @@ import java.lang.annotation.RetentionPolicy;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
+import java.security.interfaces.ECPublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.ECParameterSpec;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@@ -1442,4 +1445,50 @@ public class WifiEnterpriseConfig implements Parcelable {
}
return TextUtils.isEmpty(getCaPath());
}
+
+ /**
+ * Check if a given certificate Get the Suite-B cipher from the certificate
+ *
+ * @param x509Certificate Certificate to process
+ * @return true if the certificate OID matches the Suite-B requirements for RSA or ECDSA
+ * certificates, or false otherwise.
+ * @hide
+ */
+ public static boolean isSuiteBCipherCert(@Nullable X509Certificate x509Certificate) {
+ if (x509Certificate == null) {
+ return false;
+ }
+ final String sigAlgOid = x509Certificate.getSigAlgOID();
+
+ // Wi-Fi alliance requires the use of both ECDSA secp384r1 and RSA 3072 certificates
+ // in WPA3-Enterprise 192-bit security networks, which are also known as Suite-B-192
+ // networks, even though NSA Suite-B-192 mandates ECDSA only. The use of the term
+ // Suite-B was already coined in the IEEE 802.11-2016 specification for
+ // AKM 00-0F-AC but the test plan for WPA3-Enterprise 192-bit for APs mandates
+ // support for both RSA and ECDSA, and for STAs it mandates ECDSA and optionally
+ // RSA. In order to be compatible with all WPA3-Enterprise 192-bit deployments,
+ // we are supporting both types here.
+ if (sigAlgOid.equals("1.2.840.113549.1.1.12")) {
+ // sha384WithRSAEncryption
+ if (x509Certificate.getPublicKey() instanceof RSAPublicKey) {
+ final RSAPublicKey rsaPublicKey = (RSAPublicKey) x509Certificate.getPublicKey();
+ if (rsaPublicKey.getModulus() != null
+ && rsaPublicKey.getModulus().bitLength() >= 3072) {
+ return true;
+ }
+ }
+ } else if (sigAlgOid.equals("1.2.840.10045.4.3.3")) {
+ // ecdsa-with-SHA384
+ if (x509Certificate.getPublicKey() instanceof ECPublicKey) {
+ final ECPublicKey ecPublicKey = (ECPublicKey) x509Certificate.getPublicKey();
+ final ECParameterSpec ecParameterSpec = ecPublicKey.getParams();
+
+ if (ecParameterSpec != null && ecParameterSpec.getOrder() != null
+ && ecParameterSpec.getOrder().bitLength() >= 384) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
index b0213b0ef502..e12bb9178235 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSpecifier.java
@@ -78,12 +78,12 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc
private @Nullable String mWpa3SaePassphrase;
/**
* The enterprise configuration details specifying the EAP method,
- * certificates and other settings associated with the WPA-EAP networks.
+ * certificates and other settings associated with the WPA/WPA2-Enterprise networks.
*/
private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig;
/**
* The enterprise configuration details specifying the EAP method,
- * certificates and other settings associated with the SuiteB networks.
+ * certificates and other settings associated with the WPA3-Enterprise networks.
*/
private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
/**
@@ -243,7 +243,11 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc
/**
* Set the associated enterprise configuration for this network. Needed for authenticating
- * to WPA3-SuiteB networks. See {@link WifiEnterpriseConfig} for description.
+ * to WPA3-Enterprise networks (standard and 192-bit security). See
+ * {@link WifiEnterpriseConfig} for description. For 192-bit security networks, both the
+ * client and CA certificates must be provided, and must be of type of either
+ * sha384WithRSAEncryption (OID 1.2.840.113549.1.1.12) or ecdsa-with-SHA384
+ * (OID 1.2.840.10045.4.3.3).
*
* @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
* @return Instance of {@link Builder} to enable chaining of the builder method.
@@ -284,8 +288,25 @@ public final class WifiNetworkSpecifier extends NetworkSpecifier implements Parc
} else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
configuration.enterpriseConfig = mWpa2EnterpriseConfig;
- } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
- configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
+ } else if (mWpa3EnterpriseConfig != null) { // WPA3-Enterprise
+ if (mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS
+ && WifiEnterpriseConfig.isSuiteBCipherCert(
+ mWpa3EnterpriseConfig.getClientCertificate())
+ && WifiEnterpriseConfig.isSuiteBCipherCert(
+ mWpa3EnterpriseConfig.getCaCertificate())) {
+ // WPA3-Enterprise in 192-bit security mode (Suite-B)
+ configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
+ } else {
+ // WPA3-Enterprise
+ configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+ configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+ configuration.allowedPairwiseCiphers.set(
+ WifiConfiguration.PairwiseCipher.GCMP_256);
+ configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+ configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
+ configuration.requirePmf = true;
+ }
configuration.enterpriseConfig = mWpa3EnterpriseConfig;
} else if (mIsEnhancedOpen) { // OWE network
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
diff --git a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
index 68eb1bbd8a79..d8be1d2c853c 100644
--- a/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
+++ b/wifi/java/android/net/wifi/WifiNetworkSuggestion.java
@@ -72,12 +72,12 @@ public final class WifiNetworkSuggestion implements Parcelable {
private @Nullable String mWpa3SaePassphrase;
/**
* The enterprise configuration details specifying the EAP method,
- * certificates and other settings associated with the WPA-EAP networks.
+ * certificates and other settings associated with the WPA/WPA2-Enterprise networks.
*/
private @Nullable WifiEnterpriseConfig mWpa2EnterpriseConfig;
/**
* The enterprise configuration details specifying the EAP method,
- * certificates and other settings associated with the SuiteB networks.
+ * certificates and other settings associated with the WPA3-Enterprise networks.
*/
private @Nullable WifiEnterpriseConfig mWpa3EnterpriseConfig;
/**
@@ -276,7 +276,11 @@ public final class WifiNetworkSuggestion implements Parcelable {
/**
* Set the associated enterprise configuration for this network. Needed for authenticating
- * to WPA3 enterprise networks. See {@link WifiEnterpriseConfig} for description.
+ * to WPA3-Enterprise networks (standard and 192-bit security). See
+ * {@link WifiEnterpriseConfig} for description. For 192-bit security networks, both the
+ * client and CA certificates must be provided, and must be of type of either
+ * sha384WithRSAEncryption (OID 1.2.840.113549.1.1.12) or ecdsa-with-SHA384
+ * (OID 1.2.840.10045.4.3.3).
*
* @param enterpriseConfig Instance of {@link WifiEnterpriseConfig}.
* @return Instance of {@link Builder} to enable chaining of the builder method.
@@ -522,8 +526,25 @@ public final class WifiNetworkSuggestion implements Parcelable {
} else if (mWpa2EnterpriseConfig != null) { // WPA-EAP network
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
configuration.enterpriseConfig = mWpa2EnterpriseConfig;
- } else if (mWpa3EnterpriseConfig != null) { // WPA3-SuiteB network
- configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
+ } else if (mWpa3EnterpriseConfig != null) { // WPA3-Enterprise
+ if (mWpa3EnterpriseConfig.getEapMethod() == WifiEnterpriseConfig.Eap.TLS
+ && WifiEnterpriseConfig.isSuiteBCipherCert(
+ mWpa3EnterpriseConfig.getClientCertificate())
+ && WifiEnterpriseConfig.isSuiteBCipherCert(
+ mWpa3EnterpriseConfig.getCaCertificate())) {
+ // WPA3-Enterprise in 192-bit security mode (Suite-B)
+ configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP_SUITE_B);
+ } else {
+ // WPA3-Enterprise
+ configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_EAP);
+ configuration.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
+ configuration.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
+ configuration.allowedPairwiseCiphers.set(
+ WifiConfiguration.PairwiseCipher.GCMP_256);
+ configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
+ configuration.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.GCMP_256);
+ configuration.requirePmf = true;
+ }
configuration.enterpriseConfig = mWpa3EnterpriseConfig;
} else if (mIsEnhancedOpen) { // OWE network
configuration.setSecurityParams(WifiConfiguration.SECURITY_TYPE_OWE);
diff --git a/wifi/tests/src/android/net/wifi/FakeKeys.java b/wifi/tests/src/android/net/wifi/FakeKeys.java
index 641b891a1f4d..c0d60c33f99c 100644
--- a/wifi/tests/src/android/net/wifi/FakeKeys.java
+++ b/wifi/tests/src/android/net/wifi/FakeKeys.java
@@ -214,35 +214,6 @@ public class FakeKeys {
};
public static final PrivateKey RSA_KEY1 = loadPrivateRSAKey(FAKE_RSA_KEY_1);
- private static final String CLIENT_SUITE_B_RSA3072_CERT_STRING =
- "-----BEGIN CERTIFICATE-----\n"
- + "MIIERzCCAq8CFDopjyNgaj+c2TN2k06h7okEWpHJMA0GCSqGSIb3DQEBDAUAMF4x\n"
- + "CzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEMMAoGA1UEBwwDTVRWMRAwDgYDVQQK\n"
- + "DAdBbmRyb2lkMQ4wDAYDVQQLDAVXaS1GaTESMBAGA1UEAwwJdW5pdGVzdENBMB4X\n"
- + "DTIwMDcyMTAyMjkxMVoXDTMwMDUzMDAyMjkxMVowYjELMAkGA1UEBhMCVVMxCzAJ\n"
- + "BgNVBAgMAkNBMQwwCgYDVQQHDANNVFYxEDAOBgNVBAoMB0FuZHJvaWQxDjAMBgNV\n"
- + "BAsMBVdpLUZpMRYwFAYDVQQDDA11bml0ZXN0Q2xpZW50MIIBojANBgkqhkiG9w0B\n"
- + "AQEFAAOCAY8AMIIBigKCAYEAwSK3C5K5udtCKTnE14e8z2cZvwmB4Xe+a8+7QLud\n"
- + "Hooc/lQzClgK4MbVUC0D3FE+U32C78SxKoTaRWtvPmNm+UaFT8KkwyUno/dv+2XD\n"
- + "pd/zARQ+3FwAfWopAhEyCVSxwsCa+slQ4juRIMIuUC1Mm0NaptZyM3Tj/ICQEfpk\n"
- + "o9qVIbiK6eoJMTkY8EWfAn7RTFdfR1OLuO0mVOjgLW9/+upYv6hZ19nAMAxw4QTJ\n"
- + "x7lLwALX7B+tDYNEZHDqYL2zyvQWAj2HClere8QYILxkvktgBg2crEJJe4XbDH7L\n"
- + "A3rrXmsiqf1ZbfFFEzK9NFqovL+qGh+zIP+588ShJFO9H/RDnDpiTnAFTWXQdTwg\n"
- + "szSS0Vw2PB+JqEABAa9DeMvXT1Oy+NY3ItPHyy63nQZVI2rXANw4NhwS0Z6DF+Qs\n"
- + "TNrj+GU7e4SG/EGR8SvldjYfQTWFLg1l/UT1hOOkQZwdsaW1zgKyeuiFB2KdMmbA\n"
- + "Sq+Ux1L1KICo0IglwWcB/8nnAgMBAAEwDQYJKoZIhvcNAQEMBQADggGBAMYwJkNw\n"
- + "BaCviKFmReDTMwWPRy4AMNViEeqAXgERwDEKwM7efjsaj5gctWfKsxX6UdLzkhgg\n"
- + "6S/T6PxVWKzJ6l7SoOuTa6tMQOZp+h3R1mdfEQbw8B5cXBxZ+batzAai6Fiy1FKS\n"
- + "/ka3INbcGfYuIYghfTrb4/NJKN06ZaQ1bpPwq0e4gN7800T2nbawvSf7r+8ZLcG3\n"
- + "6bGCjRMwDSIipNvOwoj3TG315XC7TccX5difQ4sKOY+d2MkVJ3RiO0Ciw2ZbEW8d\n"
- + "1FH5vUQJWnBUfSFznosGzLwH3iWfqlP+27jNE+qB2igEwCRFgVAouURx5ou43xuX\n"
- + "qf6JkdI3HTJGLIWxkp7gOeln4dEaYzKjYw+P0VqJvKVqQ0IXiLjHgE0J9p0vgyD6\n"
- + "HVVcP7U8RgqrbIjL1QgHU4KBhGi+WSUh/mRplUCNvHgcYdcHi/gHpj/j6ubwqIGV\n"
- + "z4iSolAHYTmBWcLyE0NgpzE6ntp+53r2KaUJA99l2iGVzbWTwqPSm0XAVw==\n"
- + "-----END CERTIFICATE-----\n";
- public static final X509Certificate CLIENT_SUITE_B_RSA3072_CERT =
- loadCertificate(CLIENT_SUITE_B_RSA3072_CERT_STRING);
-
private static X509Certificate loadCertificate(String blob) {
try {
final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
diff --git a/wifi/tests/src/android/net/wifi/ScanResultTest.java b/wifi/tests/src/android/net/wifi/ScanResultTest.java
index 5516f433070f..f1ec5e829316 100644
--- a/wifi/tests/src/android/net/wifi/ScanResultTest.java
+++ b/wifi/tests/src/android/net/wifi/ScanResultTest.java
@@ -102,9 +102,10 @@ public class ScanResultTest {
5845, WifiScanner.WIFI_BAND_5_GHZ, 169,
5865, WifiScanner.WIFI_BAND_5_GHZ, 173,
/* Now some 6GHz channels */
- 5945, WifiScanner.WIFI_BAND_6_GHZ, 1,
- 5960, WifiScanner.WIFI_BAND_6_GHZ, 4,
- 6100, WifiScanner.WIFI_BAND_6_GHZ, 32
+ 5955, WifiScanner.WIFI_BAND_6_GHZ, 1,
+ 5935, WifiScanner.WIFI_BAND_6_GHZ, 2,
+ 5970, WifiScanner.WIFI_BAND_6_GHZ, 4,
+ 6110, WifiScanner.WIFI_BAND_6_GHZ, 32
};
/**
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
index d78c942d55e2..1a4427034756 100644
--- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
@@ -282,6 +282,12 @@ public class SoftApConfigurationTest {
.build();
assertNull(band_6g_config.toWifiConfiguration());
+ SoftApConfiguration sae_transition_config = new SoftApConfiguration.Builder()
+ .setPassphrase("secretsecret",
+ SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)
+ .build();
+
+ assertNull(sae_transition_config.toWifiConfiguration());
}
@Test
@@ -324,16 +330,5 @@ public class SoftApConfigurationTest {
assertThat(wifiConfig_2g5g.apBand).isEqualTo(WifiConfiguration.AP_BAND_ANY);
assertThat(wifiConfig_2g5g.apChannel).isEqualTo(0);
assertThat(wifiConfig_2g5g.hiddenSSID).isEqualTo(true);
-
- SoftApConfiguration softApConfig_sae_transition = new SoftApConfiguration.Builder()
- .setPassphrase("secretsecret",
- SoftApConfiguration.SECURITY_TYPE_WPA3_SAE_TRANSITION)
- .build();
-
- WifiConfiguration wifiConfig_sae_transition =
- softApConfig_sae_transition.toWifiConfiguration();
- assertThat(wifiConfig_sae_transition.getAuthType())
- .isEqualTo(WifiConfiguration.KeyMgmt.WPA2_PSK);
- assertThat(wifiConfig_sae_transition.preSharedKey).isEqualTo("secretsecret");
}
}
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 8270d643ca65..638efb9f14ee 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -23,8 +23,6 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
-import android.net.wifi.EAPConstants;
-import android.net.wifi.FakeKeys;
import android.net.wifi.hotspot2.pps.Credential;
import android.net.wifi.hotspot2.pps.HomeSp;
import android.os.Parcel;
@@ -34,11 +32,6 @@ import androidx.test.filters.SmallTest;
import org.junit.Test;
import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.PrivateKey;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -390,39 +383,19 @@ public class PasspointConfigurationTest {
}
/**
- * Verify that the unique identifier generated is the same for two instances with different
- * HomeSp node but same FQDN
+ * Verify that the unique identifier generated is different for two instances with different
+ * HomeSp node
*
* @throws Exception
*/
@Test
- public void validateUniqueIdDifferentHomeSpSameFqdn() throws Exception {
+ public void validateUniqueIdDifferentHomeSp() throws Exception {
PasspointConfiguration config1 = PasspointTestUtils.createConfig();
- // Modify config2's RCOIs and friendly name to a different set of values
+ // Modify config2's RCOIs to a different set of values
PasspointConfiguration config2 = PasspointTestUtils.createConfig();
HomeSp homeSp = config2.getHomeSp();
homeSp.setRoamingConsortiumOis(new long[] {0xaa, 0xbb});
- homeSp.setFriendlyName("Some other name");
- config2.setHomeSp(homeSp);
-
- assertEquals(config1.getUniqueId(), config2.getUniqueId());
- }
-
- /**
- * Verify that the unique identifier generated is different for two instances with the same
- * HomeSp node but different FQDN
- *
- * @throws Exception
- */
- @Test
- public void validateUniqueIdSameHomeSpDifferentFqdn() throws Exception {
- PasspointConfiguration config1 = PasspointTestUtils.createConfig();
-
- // Modify config2's FQDN to a different value
- PasspointConfiguration config2 = PasspointTestUtils.createConfig();
- HomeSp homeSp = config2.getHomeSp();
- homeSp.setFqdn("fqdn2.com");
config2.setHomeSp(homeSp);
assertNotEquals(config1.getUniqueId(), config2.getUniqueId());
@@ -430,15 +403,15 @@ public class PasspointConfigurationTest {
/**
* Verify that the unique identifier generated is different for two instances with different
- * SIM Credential node
+ * Credential node
*
* @throws Exception
*/
@Test
- public void validateUniqueIdDifferentSimCredential() throws Exception {
+ public void validateUniqueIdDifferentCredential() throws Exception {
PasspointConfiguration config1 = PasspointTestUtils.createConfig();
- // Modify config2's realm and SIM credential to a different set of values
+ // Modify config2's RCOIs to a different set of values
PasspointConfiguration config2 = PasspointTestUtils.createConfig();
Credential credential = config2.getCredential();
credential.setRealm("realm2.example.com");
@@ -449,157 +422,6 @@ public class PasspointConfigurationTest {
}
/**
- * Verify that the unique identifier generated is different for two instances with different
- * Realm in the Credential node
- *
- * @throws Exception
- */
- @Test
- public void validateUniqueIdDifferentRealm() throws Exception {
- PasspointConfiguration config1 = PasspointTestUtils.createConfig();
-
- // Modify config2's realm to a different set of values
- PasspointConfiguration config2 = PasspointTestUtils.createConfig();
- Credential credential = config2.getCredential();
- credential.setRealm("realm2.example.com");
- config2.setCredential(credential);
-
- assertNotEquals(config1.getUniqueId(), config2.getUniqueId());
- }
-
- /**
- * Verify that the unique identifier generated is the same for two instances with different
- * password and same username in the User Credential node
- *
- * @throws Exception
- */
- @Test
- public void validateUniqueIdSameUserInUserCredential() throws Exception {
- PasspointConfiguration config1 = PasspointTestUtils.createConfig();
- Credential credential = createCredentialWithUserCredential("user", "passwd");
- config1.setCredential(credential);
-
- // Modify config2's Passpowrd to a different set of values
- PasspointConfiguration config2 = PasspointTestUtils.createConfig();
- credential = createCredentialWithUserCredential("user", "newpasswd");
- config2.setCredential(credential);
-
- assertEquals(config1.getUniqueId(), config2.getUniqueId());
- }
-
- /**
- * Verify that the unique identifier generated is different for two instances with different
- * username in the User Credential node
- *
- * @throws Exception
- */
- @Test
- public void validateUniqueIdDifferentUserCredential() throws Exception {
- PasspointConfiguration config1 = PasspointTestUtils.createConfig();
- Credential credential = createCredentialWithUserCredential("user", "passwd");
- config1.setCredential(credential);
-
- // Modify config2's username to a different value
- PasspointConfiguration config2 = PasspointTestUtils.createConfig();
- credential = createCredentialWithUserCredential("user2", "passwd");
- config2.setCredential(credential);
-
- assertNotEquals(config1.getUniqueId(), config2.getUniqueId());
- }
-
- /**
- * Verify that the unique identifier generated is different for two instances with different
- * Cert Credential node
- *
- * @throws Exception
- */
- @Test
- public void validateUniqueIdDifferentCertCredential() throws Exception {
- PasspointConfiguration config1 = PasspointTestUtils.createConfig();
- Credential credential = createCredentialWithCertificateCredential(true, true);
- config1.setCredential(credential);
-
- // Modify config2's cert credential to a different set of values
- PasspointConfiguration config2 = PasspointTestUtils.createConfig();
- credential = createCredentialWithCertificateCredential(false, false);
- config2.setCredential(credential);
-
- assertNotEquals(config1.getUniqueId(), config2.getUniqueId());
- }
-
- /**
- * Helper function for generating certificate credential for testing.
- *
- * @return {@link Credential}
- */
- private static Credential createCredentialWithCertificateCredential(Boolean useCaCert0,
- Boolean useCert0)
- throws NoSuchAlgorithmException, CertificateEncodingException {
- Credential.CertificateCredential certCred = new Credential.CertificateCredential();
- certCred.setCertType("x509v3");
- if (useCert0) {
- certCred.setCertSha256Fingerprint(
- MessageDigest.getInstance("SHA-256").digest(FakeKeys.CLIENT_CERT.getEncoded()));
- } else {
- certCred.setCertSha256Fingerprint(MessageDigest.getInstance("SHA-256")
- .digest(FakeKeys.CLIENT_SUITE_B_RSA3072_CERT.getEncoded()));
- }
- return createCredential(null, certCred, null, new X509Certificate[] {FakeKeys.CLIENT_CERT},
- FakeKeys.RSA_KEY1, useCaCert0 ? FakeKeys.CA_CERT0 : FakeKeys.CA_CERT1);
- }
-
- /**
- * Helper function for generating user credential for testing.
- *
- * @return {@link Credential}
- */
- private static Credential createCredentialWithUserCredential(String username, String password) {
- Credential.UserCredential userCred = new Credential.UserCredential();
- userCred.setUsername(username);
- userCred.setPassword(password);
- userCred.setMachineManaged(true);
- userCred.setAbleToShare(true);
- userCred.setSoftTokenApp("TestApp");
- userCred.setEapType(EAPConstants.EAP_TTLS);
- userCred.setNonEapInnerMethod("MS-CHAP");
- return createCredential(userCred, null, null, null, null, FakeKeys.CA_CERT0);
- }
-
- /**
- * Helper function for generating Credential for testing.
- *
- * @param userCred Instance of UserCredential
- * @param certCred Instance of CertificateCredential
- * @param simCred Instance of SimCredential
- * @param clientCertificateChain Chain of client certificates
- * @param clientPrivateKey Client private key
- * @param caCerts CA certificates
- * @return {@link Credential}
- */
- private static Credential createCredential(Credential.UserCredential userCred,
- Credential.CertificateCredential certCred,
- Credential.SimCredential simCred,
- X509Certificate[] clientCertificateChain, PrivateKey clientPrivateKey,
- X509Certificate... caCerts) {
- Credential cred = new Credential();
- cred.setCreationTimeInMillis(123455L);
- cred.setExpirationTimeInMillis(2310093L);
- cred.setRealm("realm");
- cred.setCheckAaaServerCertStatus(true);
- cred.setUserCredential(userCred);
- cred.setCertCredential(certCred);
- cred.setSimCredential(simCred);
- if (caCerts != null && caCerts.length == 1) {
- cred.setCaCertificate(caCerts[0]);
- } else {
- cred.setCaCertificates(caCerts);
- }
- cred.setClientCertificateChain(clientCertificateChain);
- cred.setClientPrivateKey(clientPrivateKey);
- return cred;
- }
-
- /**
* Verify that the unique identifier API generates an exception if HomeSP is not initialized.
*
* @throws Exception
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
index a44df40a8e97..829d8f0a9a3a 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/pps/CredentialTest.java
@@ -593,10 +593,10 @@ public class CredentialTest {
}
/**
- * Verify that unique identifiers are different for a credential with different username
+ * Verify that unique identifiers are different for a credential with different values
*/
@Test
- public void testUniqueIdDifferentForUserCredentialsWithDifferentUsername() throws Exception {
+ public void testUniqueIdDifferentForUserCredentialsWithDifferentValues() throws Exception {
Credential userCred1 = createCredentialWithUserCredential();
Credential userCred2 = createCredentialWithUserCredential();
userCred2.getUserCredential().setUsername("anotheruser");
@@ -605,24 +605,7 @@ public class CredentialTest {
}
/**
- * Verify that unique identifiers are different for a credential with different password and
- * other values other than username
- */
- @Test
- public void testUniqueIdSameForUserCredentialsWithDifferentPassword() throws Exception {
- Credential userCred1 = createCredentialWithUserCredential();
- Credential userCred2 = createCredentialWithUserCredential();
- userCred2.getUserCredential().setPassword("someotherpassword!");
- userCred2.getUserCredential().setMachineManaged(false);
- userCred2.getUserCredential().setAbleToShare(false);
- userCred2.getUserCredential().setSoftTokenApp("TestApp2");
- userCred2.getUserCredential().setNonEapInnerMethod("PAP");
-
- assertEquals(userCred1.getUniqueId(), userCred2.getUniqueId());
- }
-
- /**
- * Verify that unique identifiers are different for a cert credential with different values
+ * Verify that unique identifiers are different for a credential with different values
*/
@Test
public void testUniqueIdDifferentForCertCredentialsWithDifferentValues() throws Exception {